プロが教える店舗&オフィスのセキュリティ対策術

 こんにちは
 Javamailを使ってAndroid用メールアプリの開発を志しているものです。
 以下のサイトを参考にさせてもらってコードを作ってエミュレーターで動かしてみました。
http://yamato-iphone.blogspot.jp/2011/12/javamai …
http://d.hatena.ne.jp/ttshrk/20110517/1305641955
http://yaim.blogzine.jp/ability/2012/04/javamail …

 ところが、下記のようなエラーで、メール送信ができませんでした。
12-23 10:56:36.225: W/System.err(541): javax.mail.MessagingException: Could not connect to SMTP host: smtp.hogehoge.jp, port: 587;
12-23 10:56:36.225: W/System.err(541): nested exception is:
12-23 10:56:36.235: W/System.err(541): javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x199c48: Failure in SSL library, usually a protocol error
12-23 10:56:36.235: W/System.err(541): error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol (external/openssl/ssl/s23_clnt.c:683 0x401e0c93:0x00000000)

 また、
12-23 10:56:35.385: I/System.out(541): DEBUG: not loading file: /system/lib/javamail.providers
12-23 10:56:35.385: I/System.out(541): DEBUG: java.io.FileNotFoundException: /system/lib/javamail.providers: open failed: ENOENT (No such file or directory)
 このようなログも吐き出されており、なにか足りないものがあるようなのですが…

 単純なサンプルアプリなどは普通に動作していますので、開発環境にとりあえず不備はないと思います。
 Javamail用の3つのファイルもビルドパスに加えてあります。
 その他にも追加すべきライブラリがあるのでしょうか?
 これだけの情報では、ご回答いただくのは難しいのかも知れませんが…

 よろしくお願いいたします。

A 回答 (4件)

ENOENT は「ファイルがない」ということを表しています。

まずはこれを確認して欲しいです。
/system/lib/javamail.providers

例外をcatchして、ログへe.getMessage()することで、詳細を得られないでしょうか…。

import android.util.Log

この回答への補足

 つたない質問にご回答いただきありがとうございます。

 さて、
/system/lib/javamail.providers
 は、確かに存在していませんでした。
 ただ、ログを見ていると、
12-23 14:23:03.403: I/System.out(952): DEBUG: not loading file: /system/lib/javamail.providers
12-23 14:23:03.403: I/System.out(952): DEBUG: java.io.FileNotFoundException: /system/lib/javamail.providers: open failed: ENOENT (No such file or directory)
12-23 14:23:03.413: I/System.out(952): DEBUG: !anyLoaded
12-23 14:23:03.413: I/System.out(952): DEBUG: not loading resource: /META-INF/javamail.providers
12-23 14:23:03.443: I/System.out(952): DEBUG: not loading resource: /META-INF/javamail.default.providers
12-23 14:23:03.443: I/System.out(952): DEBUG: failed to load any providers, using defaults
12-23 14:23:03.443: I/System.out(952): DEBUG: Tables of loaded providers
 といったふうに、デフォルトのものを使ってくれているのかな…と考えておりました。

 次に、e.getMessage()ですが、
Could not connect to SMTP host: smtp.hogehoge.jp, port: 587
 出してくれたログはこれだけでした。
 メールソフトでは587ポートで接続しているので、サーバー側の問題ではないと思っています。

 このような感じなのですが、いかがでしょうか?

補足日時:2012/12/23 23:46
    • good
    • 0

javamail.providerによって、プロトコルと、使用するクラスを対応付けしているのでデフォルトであれば、ご自身の環境で適切なクラスを示すことができているかを確認してください。



http://www2s.biglobe.ne.jp/~dat/java/classes/jav …


---

http://yamato-iphone.blogspot.jp/2011/12/javamai …

上記URLで示されているところの、
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(mUser, mPassword);
}

はされていますか?

すなわち、SMTPサーバーに接続する際に、認証が必要ではありませんか?

発生したメソッドを特定したいのでe.getStackTrace()も取得してみますか。

この回答への補足

 ご回答ありがとうございます。
 教えて頂いたサイトを参考にして、javamail.providersというファイル作成し、SMTPSSLTransportにかえてみました。
 が、
not loading file: /system/lib/javamail.providers
 は相変わらずでした…

 また、Authenticatorについては、セッションのgetInstanceで実行しています。
 使用しているSMTPサーバーは認証が必要です。
 ちなみに、POP Before SMTPも必要なので、POP3接続をしています。
 POP3sはエラーですが、SSL無しなら問題なく接続できているようです。
 SSL接続するために、こちら側にサーバー証明書は必要なのでしょうか?

 最後にe.printStackTrace()の結果を一部掲載します。
javax.mail.MessagingException: Could not connect to SMTP host: smtp.hogehoge.jp, port: 587;
nested exception is:
javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x13cbd8: Failure in SSL library, usually a protocol error
error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol (external/openssl/ssl/s23_clnt.c:683 0x401e0c93:0x00000000)
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1391)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:412)
at javax.mail.Service.connect(Service.java:288)
at jp.hogehoge.mail_service.SendMail.Send_Mail(SendMail.java:93)

 最後の行のSend_Mailが自作のメソッドです。
 これで分かりますでしょうか?

 よろしくお願いします。

補足日時:2012/12/25 17:07
    • good
    • 0

http://siisise.net/java/net/

仰るとおり、証明書の問題だと思います。

Propertiesクラスの変数に以下の引数を与えてsetPropertyしてください。

## foo.setProperty("mail.smtp.socketFactory.class","javax.net.ssl.SSLSocketFactory");


これでNGでしたら、Propetiesの組立からメール送信の部分を差し支えない範囲で開示いただけると良いかと存じます。

この回答への補足

 再三にわたるご回答誠にありがとうございます。
 仰るとおり、最初からソースコードをここに貼り付けるべきでした…
 申し訳ございませんでした。
 問題のメソッドは以下の通りです。
 一部改変しております

public void Send_Mail() {

StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitAll().build());

final String mUser = "foo@hogehoge.jp";
final String mpwd = "password";

Properties props = new Properties();
//Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
//上記の一行はエラーになるためコメントアウトしています。
props.setProperty("mail.debug", "true");
props.setProperty("mail.smtp.user", mUser);
props.setProperty("mail.smtp.host", "smtp.hogehoge.jp");
props.setProperty("mail.smtp.port", "587");
props.setProperty("mail.smtp.socketFactory.port", "587");
props.setProperty("mail.smtp.auth", "true");
props.setProperty("mail.smtp.starttls.enable", "true");
props.setProperty("mail.smtp.ssl.trust", "smtp.hogehoge.jp");
props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.setProperty("mail.smtp.socketFactory.fallback", "false");

//Session sess = Session.getInstance(props);
//上記1行は認証のため下記4行に書き換え
Session sess = Session.getInstance(props, new Authenticator(){
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication( mUser, mpwd );
}
});
sess.setDebug(true);

try {
final MimeMessage mimeMsg = new MimeMessage(sess);

//POP Before SMTP
Store store = sess.getStore("pop3");
//上記"pop3"を"pop3s"に変えると、証明書が見つからない旨のエラー
store.connect("mail.hogehoge.jp", mUser, mpwd );

mimeMsg.setFrom(new InternetAddress(mUser));
mimeMsg.setRecipient(Message.RecipientType.TO, new InternetAddress("foo@hogehoge.jp"));
mimeMsg.setContent("body", "text/plain; utf-8");
mimeMsg.setHeader("Content-Transfer-Encoding", "7bit");
mimeMsg.setSubject("テスト送信");
mimeMsg.setText("アンドロイドからの送信", "utf-8");
mimeMsg.setSentDate( new Date() );

//Transport.send(mimeMsg);
//上記1行は認証のため下記4行に書き換え
Transport transport = sess.getTransport("smtps");
transport.connect("smtp.hogehoge.jp",587,mUser, mpwd);
transport.sendMessage(mimeMsg, mimeMsg.getAllRecipients());// メール送信
transport.close();

} catch (Exception e) {
Log.v("tag",e.getMessage());
e.printStackTrace();
}
}

 以上です。
 いろいろな方のコードを切り貼りさせて貰っております。
 大前提として、SSL通信を行う場合には、証明書をインストールする必要があるのでしょうか?
 もしそうなら、アンドロイド端末にも、証明書が必要なのでしょうか?

 よろしくお願いします。

補足日時:2012/12/26 11:43
    • good
    • 0

・POP3Sのポート番号は確認したほうがよいと思います。

(POP3と同じでしょうか?)

・SMTPのプロパティをprops.setPropertyしているように、POPについても同様にsetPropertyする必要があると考えます。

少なくても、Store store = sess.getStore("pop3s"); ならば、 props.setProperty("mail.pop.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); は必要ではないかという認識です。


http://javamail.kenai.com/nonav/javadocs/com/sun …

http://www.igapyon.jp/igapyon/diary/2007/ig07090 …

この回答への補足

 いつもありがとうございます。

 私が余計なことを書いたために論点がずれてしまいました。
 問題は先に貼り付けたコードで前述のようなエラーが発生しているということです。
 POP接続についても、問題は問題ですが、SMTPがSSLで接続できれば自ずと解決するものと思っております。

 いろいろなサイトで公開されているコードを参考にさせて頂きましたが、大体これくらいのコードで接続できているということなのですが…

 コードを見る限り、SMTP接続についてはいけそうな感じでしょうか?
 もしそうなら、なにが原因で接続できないか、思い当たられることはありますでしょうか?

 度々恐縮なのですが、よろしくお願いいたします。

補足日時:2012/12/27 15:18
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!