Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。
評価

0

携帯からのJavaMailについて

現在以下のようなソースをサーバ上で動かしており、主に携帯電話からアクセスされると動作します。

import bean.*;
import java.util.Date;
import java.util.Properties;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;

public class MailSender
{
    public MailSender()
    {
    }

    public void send(EntryMemberBean member,SettingFile set,HttpServletRequest req,HttpServletResponse res)
        throws Exception
    {
        HttpSession sessions = req.getSession();

        try{

        // 初期設定
            Properties props = new Properties();
            // 接続するSMTP
            props.put("mail.smtp.host", "XX.co.jp");
            // SMTP before POP3対応
            props.put("mail.smtp.auth","true");
            // JavaMailのデバッグモード
            props.put("mail.debug", "true");
            // ポートの設定
            props.put("mail.smtp.port", String.valueOf("25"));
            // 接続するホスト名
            props.put("mail.host","XXX@XXX");
            //接続タイムアウト
            props.put("mail.smtp.connectiontimeout", String.valueOf(50000));
            //送受信タイムアウト
            props.put("mail.smtp.timeout",String.valueOf(50000));

            Session sess = Session.getInstance (props);

            MimeMessage mimeMessage = new MimeMessage(sess);
            // 送信元メールアドレスと送信者名を指定
            mimeMessage.setFrom(new InternetAddress("XX@XX.co.jp", "XXX","iso-2022-jp"));

            // 送信先メールアドレスを指定
            mimeMessage.setRecipients(Message.RecipientType.TO, "XX@XX.co.jp");

            // 件名
            mimeMessage.setSubject("メールテスト","iso-2022-jp");

            // 送信日時
            mimeMessage.setSentDate( new Date());

            // 本文
            mimeMessage.setText("メールのテスト送信です。","iso-2022-jp");

            Transport transport = sess.getTransport("smtp");
            // 認証用ユーザ名とパスワードを設定しコネクト
            transport.connect(null,"XXXXXX(アカウント)","XXXXXX(パスワード)");
            // メール送信
             transport.sendMessage( mimeMessage,mimeMessage.getAllRecipients());
            // クローズ
            transport.close();

        }catch (Exception e){
            e.printStackTrace();
            sessions.setAttribute("errmsg", "aaa");
            req.getRequestDispatcher("error.jsp").forward(req, res);
        }
    }
}

IEなどからアクセスした場合は上手く行くのですが、携帯(特にau端末)でアクセスした場合失敗します。

au端末でアクセスした場合以下のエラーが表示されます。
「EZサーバからの応答がありません。しばらくたってからリトライしてください」

25

回答

7952

閲覧

25件の回答

評価

0

で、何をどう調べて何を訊きたいの。

評価

0

すみません、言葉足らずでした。

コード上は問題ないと思うのですが、携帯からのアクセス
がなぜ失敗するのかが知りたいのです。

各ソース上でログを出力させて調査をしてみたところ、transport.sendMessageの処理に30秒近く時間がかかっていることが判っております。

携帯サイトのメール送信フォームをJavaMailで作った事のある方がいらっしゃいましたら、何かご助言をいただけると助かります。

評価

0

アクセス元が何かなんて、JavaMailには関係のない話。
送信で差異が出るというなら、送信元のホストが違うか、送信先のホストが違うか、送信するメッセージの情報が違うか、とにかく送信というプロセス自体の違いだろう。

評価

0

サーバそのものが
au端末を拒否しているとかない?

ブサウザの履歴がいっぱいになっているときも
発生するけど。
何台の端末で確認しても同じ現象?

単純にレスポンスが悪すぎす可能性も捨てがたい。

HTTPサーバのアクセスログを確認しては?

評価

0

まず簡単なHelloWorldサーブレットで試してみようとか、考えないのかな。

評価

0

>au端末を拒否しているとかない?
携帯 - PG動作サーバ - SMTPという構成なら、端末による拒否はありえないな。
fromでの拒否なら考えられるけど、コードを見る限り固定っぽい。
PG動作サーバの話なら、Transport#send()まで来てる時点で拒否されてない。


関係ないけど

>String.valueOf("25")
>String.valueOf(50000)

定数なら単に"25"や"50000"を渡せばいい。
intを使いたい場合でも、Integer.toString(25, 10);の方がいい。

評価

0

ご返答有り難うございます。
au端末で失敗していると記載しましたがメールの送信処理は動作していました(受け取るアドレスを自分にして確認)

ただ、その送信処理が30秒以上掛かっているため、au端末だけezwebサーバからタイムエラーとしてエラー画面を出されているのではないかと考えております。

そこでメールを送信する処理を行う前に送信完了ページを表示してしまえないかと考えました。(本末転倒ですが・・・)

下記ソースは質問内容に記載したメール送信処理の呼び元です。(実際にはSessionにてメールフォームに書き入れた内容をメールにてあるアドレスへ送信する処理です。)


public class EntrySubmitServlet extends HttpServlet
{

    public EntrySubmitServlet(){}

    public void doGet(HttpServletRequest req, HttpServletResponse res)
        throws ServletException, IOException
    {
        res.setContentType("text/html; charset=Shift_JIS");
        req.setCharacterEncoding("Shift_JIS");

        HttpSession session = req.getSession();
        EntryMemberBean member = (EntryMemberBean)session.getAttribute("member");
        try{
            req.getRequestDispatcher("完了ページ.jsp").forward(req, res);

            SettingFile set = new SettingFile(getServletConfig().getServletContext().getRealPath("/")+"Property.xml");
            MailSender mail = new MailSender();
            mail.send(member,set,req,res);
            session.invalidate();
            mail = null;

        }catch (Exception e){
            e.printStackTrace();
            session.setAttribute("errmsg", new String("メール送信に失敗しました"));
            req.getRequestDispatcher("エラーページ.jsp").forward(req, res);
        }
    }
}

>>関係ないけど
ご指摘有り難うございます。
そのように修正します。

評価

0

上記のソースにて動かしたところ、やはりau端末だとEZサーバからの応答が無いと言われてしまいます。

処理の途中で完了ページを表示させるような事はできないでしょうか?

評価

0

ん?端末に関わらず30秒かかってるってこと?
処理を同時に動かしたいならスレッドにするのが確実。

評価

0

ご回答有り難うございます。
スレッドで分けてメール送信処理とメール送信完了ページを表示させる処理を同時に動かしたとしても、結局全ての処理が完了してからクライアントに応答されるのではないでしょうか?

それだと結局 全処理に30秒以上掛かってしまい、au端末でタイムエラーが起こってしまうのです。。。

評価

0

>スレッドで分けてメール送信処理と
>メール送信完了ページを表示させる処理を
>同時に動かしたとしても、結局全ての処理が
>完了してからクライアントに応答されるのではないでしょうか?

実際にやってみたの?

評価

0

すみません試しもせず決め付けておりました。

そこで下記のソースにて試してみたところメインクラス(EntrySubmitServlet)しか動いてくれませんでした。
package submit;

import bean.*;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.text.SimpleDateFormat;

class Share {
    private HttpServletRequest req;
    private HttpServletResponse res;

    public HttpServletRequest getreq() {
        return req;
    }
    public HttpServletResponse getres() {
        return res;
    }
    public void setreq(HttpServletRequest a) {
        req = a;
    }
    public void setres(HttpServletResponse a) {
        res = a;
    }
}

class SimpleSync1 extends HttpServlet implements Runnable {
    private Share pers;

    public void run() {
        HttpServletResponse res = pers.getres();
        HttpServletRequest  req = pers.getreq();

        res.setContentType("text/html; charset=Shift_JIS");
        try {
            req.setCharacterEncoding("Shift_JIS");
        } catch (UnsupportedEncodingException e2) {
            e2.printStackTrace();
        }
        HttpSession session = req.getSession();
        EntryMemberBean member = (EntryMemberBean)session.getAttribute("member");
        try{
            SettingFile set = new SettingFile(getServletConfig().getServletContext().getRealPath("/")+"Property.xml");
            MailSender mail = new MailSender();
            mail.send(member,set,req,res);
            session.invalidate();
            mail = null;

        }catch (Exception e){
            e.printStackTrace();
            session.setAttribute("errmsg", new String("メール送信に失敗しました<br><br>"));
            try {
                req.getRequestDispatcher("error.jsp").forward(req, res);
            } catch (ServletException e1) {
                e1.printStackTrace();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    }
}

class SimpleSync2 extends HttpServlet implements Runnable {
    private Share pers;

    public void run() {
        HttpServletResponse res = pers.getres();
        HttpServletRequest  req = pers.getreq();
        HttpSession session = req.getSession();
        EntryMemberBean member = (EntryMemberBean)session.getAttribute("member");
        try{
            req.getRequestDispatcher("完了ページ.jsp").forward(req, res);

        }catch (Exception e){
            e.printStackTrace();
            session.setAttribute("errmsg", new String("失敗しました<br><br>"));
            try {
                req.getRequestDispatcher("error.jsp").forward(req, res);
            } catch (ServletException e1) {
               e1.printStackTrace();
            } catch (IOException e1) {
               e1.printStackTrace();
            }
        }
    }
}

public class EntrySubmitServlet extends HttpServlet implements Runnable
{
    public EntrySubmitServlet(){}

    public void doGet(HttpServletRequest req, HttpServletResponse res)
        throws ServletException, IOException
    {
        res.setContentType("text/html; charset=Shift_JIS");
        req.setCharacterEncoding("Shift_JIS");

        try{

            SimpleSync1 sync1 = new SimpleSync1();
            Thread thre1 = new Thread(sync1);

            SimpleSync2 sync2 = new SimpleSync2();
            Thread thre2 = new Thread(sync2);

            thre1.start();
            thre2.start();

        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }
    public void run() {
    }
}
ログから、メインクラスは正常に動いているのですが、スレッドにしたメール送信処理と完了ページ表示処理がまったく動いていない状態です。 スレッドの使い方が間違っているのでしょうか??

評価

0

>private Share pers;
これどこで設定してるの?

スレッドの使い方が間違ってるというより、クラス(オブジェクト化)からなってない。
クラスを分けるなら、それぞれのクラスの役割を考えること。
シンプルに、なるべく他者への依存がない形で。

評価

0

>これどこで設定してるの?

SimpleSync1とSimpleSync2に
以下のメソッドを追加
    public void setPers(Share obj) {
        pers = obj;
    }

またEntrySubmitServlet内で
共有データクラスのインスタンス生成と設定を追加しました。
       Share pers = new Share();
    sync1.setPers(pers);
    sync2.setPers(pers);

評価

0

上記の修正を入れてもEntrySubmitServletメソッドが実行されるだけで、SimpleSync1とSimpleSync2内にあるログは出力されてませんでした。。。

>クラスを分けるなら、それぞれのクラスの役割を考えること。
SimpleSync1:メール送信処理
SimpleSync2:完了ページ表示処理
EntrySubmitServlet:上記二つの処理をコントロール(?)する処理
Share:必要なデータを共有するクラス
こんな感じで考えているのですが、何が問題なのかさっぱりわかりません。。。

評価

0

>共有データクラスのインスタンス生成と設定を追加しました。
じゃ、
>    private HttpServletRequest req;
>    private HttpServletResponse res;
これどこで設定してるの?

>SimpleSync1とSimpleSync2内にあるログは出力されてませんでした。。。
結果だけ見るんじゃなくて、そこに至るまでの経過も調査する。
どこまでちゃんと動いてるのか、どこから動かないのか。
デバッグの基本。

>SimpleSync1:メール送信処理
メール送信処理にrequestやresponseなんか関係ないじゃん。
必要なのはrequest内のパラメータじゃないの?
しかも

>extends HttpServlet

なんのために?

>SimpleSync2:完了ページ表示処理
httpへの対応は基本的にServletの役割。

評価

0

>これどこで設定してるの?
設定できてませんでした。。。
EntrySubmitServlet内に以下の処理を加えました
        pers.setreq(req);
        pers.setres(res);

>メール送信処理にrequestやresponseなんか関係ないじゃん
メール送信処理内で例外が起こった場合に
req.getRequestDispatcher("error.jsp").forward(req, res)
としているので、引数で渡しています。

>extends HttpServletは何のために?
ログを外部テキストファイルに出力するために
        String datestr2 = new SimpleDateFormat("yyyyMMdd").format( new java.util.Date() );
        String path = getServletConfig().getServletContext().getRealPath("/") + "log\\" + datestr2 + ".log";
        Log log = new Log();

log.write("XXXXXXXX",path);
などとしています。

>どこまでちゃんと動いてるのか、どこから動かないのか。
上の外部テキストへのログ出力を用いて、各クラス内でクラス開始と終了、各処理の前と後に(ほぼ1行ずつに)ログを出力させています。
そのログをみたところ、EntrySubmitServlet内のログは開始から終了まで出力されていましたが、スレッド化した二つのクラスのログは一つも出力されていない状態でした。

評価

0

EntrySubmitServlet内に以下の処理を加えました
        pers.setreq(req);
        pers.setres(res);
上記の修正を加えて動かしたところ、SimpleSync2のログ出力のための
String path = getServletConfig().getServletContext().getRealPath("/") + "log\\" + datestr2 + ".log";
で異常が起こって終了している事がわかりました。

上記の処理をログ出力クラスへ移動できないか試行錯誤中です。

評価

0

お世話になっております、回答者様方のおかげでスレッドにてメール送信と完了ページ表示処理を同時に動かす事ができましたが、結局完了ページが表示されるのはメール送信処理完了後となってしまい、タイムエラーが起こっています。
res.sendRedirect("完了ページ.jsp");
req.getRequestDispatcher("完了ページ.jsp").forward(req, res);
上記の二つの処理が効いていないのでしょうか??
再度お知恵をお貸しください、お願いします。
現在のコードは以下になります。

import bean.*;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.text.SimpleDateFormat;

class Share {
    private HttpServletRequest req;
    private HttpServletResponse res;

    public HttpServletRequest getreq() {
        return req;
    }
    public HttpServletResponse getres() {
        return res;
    }
    public void setreq(HttpServletRequest a) {
        req = a;
    }
    public void setres(HttpServletResponse a) {
        res = a;
    }
}

class SimpleSync1 implements Runnable {
    private Share pers;

    public void run() {
        HttpServletResponse res = pers.getres();
        HttpServletRequest  req = pers.getreq();
        String logpath = pers.getlogpath();

        res.setContentType("text/html; charset=Shift_JIS");
        try {
            req.setCharacterEncoding("Shift_JIS");
        } catch (UnsupportedEncodingException e2) {
            e2.printStackTrace();
        }
        HttpSession session = req.getSession();
        EntryMemberBean member = (EntryMemberBean)session.getAttribute("member");
        try{
            MailSender mail = new MailSender();
            mail.send(member,req,res);
            session.invalidate();
            mail = null;
        }catch (Exception e){
            e.printStackTrace();
            session.setAttribute("errmsg", new String("メール送信に失敗しました<br><br>"));
            try {
                req.getRequestDispatcher("エラーページ.jsp").forward(req, res);
            } catch (ServletException e1) {
                e1.printStackTrace();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    }
    public void setPers(Share obj) {
        pers = obj;
    }
}

class SimpleSync2 implements Runnable {
    Share pers;

    public void run() {
         HttpServletResponse res = pers.getres();
        HttpServletRequest  req = pers.getreq();
        HttpSession session = req.getSession();
        EntryMemberBean member = (EntryMemberBean)session.getAttribute("member");
        try{
            res.sendRedirect("完了ページ.jsp");
            req.getRequestDispatcher("done.jsp").forward(req, res);
        }catch (Exception e){
            e.printStackTrace();
            session.setAttribute("errmsg", "CSVの書き込みに失敗しました。");
            try {
                req.getRequestDispatcher("エラーページ.jsp").forward(req, res);
            } catch (ServletException e1) {
                e1.printStackTrace();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    }
    public void setPers(Share obj) {
        pers = obj;
    }
}

public class EntrySubmitServlet extends HttpServlet
{
    public EntrySubmitServlet(){}

    public void doGet(HttpServletRequest req, HttpServletResponse res)throws ServletException, IOException
    {
        res.setContentType("text/html; charset=Shift_JIS");
        req.setCharacterEncoding("Shift_JIS");
        Log log = new Log();
        try{
            Share pers = new Share();
            pers.setreq(req);
            pers.setres(res);

            SimpleSync1 sync1 = new SimpleSync1();
            Thread thre1 = new Thread(sync1);
            sync1.setPers(pers);

            SimpleSync2 sync2 = new SimpleSync2();
            Thread thre2 = new Thread(sync2);
            sync2.setPers(pers);

            thre1.start();
            thre2.start();

            thre1.join();
            thre2.join();
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }

    public void run() {
    }
}

評価

0

>メール送信処理内で例外が起こった場合に
えーと…。
送信が長すぎるからスレッドにして、さっさと完了画面を出すって話になったんじゃ?
その例外を補足するってことは、送信完了を待ってるってことじゃん…。

>ログを外部テキストファイルに出力するために
>String path = getServletConfig().getServletContext().getRealPath("/") + "log\\" + 
これ毎回変わるの?

評価

0

なんか込み入ってきてるようだけど、

1.Servletは、リクエストに対して結果画面を出すだけ。
2.メール発信は、別スレッドに放り出す。

てなことでいいんじゃないか、と思ってるんだが、
俺の思い違いがあるだろうか。

>$氏
>これ毎回変わるの?

環境に依存したくないんでしょ。
ユーティリティクラスに掃き出すべき、
という指摘だったら失礼。

評価

0

>環境に依存したくないんでしょ。
HttpServlet#init()で一回取れば十分でしょ。

評価

0

了解。
一回で済ませる方法は、いくつもあるってことで。

評価

0

>その例外を補足するってことは、送信完了を待ってるってことじゃん…。
なるほど。。。例外を補足するだけで 全体の処理を待つってことになっちゃうんですか。
ご助言を受けてメール送信処理(send)内の例外処理は無くしたのですが、メール送信処理スレッド内の例外処理は無くすとコンパイルが通らないのです。

>HttpServlet#init()で一回取れば十分でしょ。
使ってみます

評価

0

>コンパイルが通らないのです。
初心者じゃないんだから、解決方法考えてみなって…。
親のスレッドが、例外処理に関係しなきゃいいんでしょ?

質問から6ヶ月以上経過しているので、回答を書き込むことはできません。