20

javax.mailAPIを使用してメールを送信できます。ただし、ここでの問題は、メールごとに平均して宛先に送信するのに約4.3秒かかることです。

20通のメールを連続して送信する場合、約86.599秒かかります。私の要件では、このアプローチは機能しません。短時間で大量のメールを送信できるアプローチを探しています。

デバッグログを見ると、APIは送信するすべてのメッセージについてSMTPサーバーに対して認証を試みています。ただし、セッションを1回だけ作成し、送信するすべてのメールに同じセッションを使用しています。今私の質問は、SMTPサーバーに対して自分自身を認証するたびにオーバーヘッドプロセスではないかということです。より良いアプローチはありませんか?

以下は、役立つと思われるログトレースです。

250-AUTH LOGIN PLAIN XOAUTH XOAUTH2
250 ENHANCEDSTATUSCODES
DEBUG SMTP: Found extension "SIZE", arg "35882577"
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "AUTH", arg "LOGIN PLAIN XOAUTH XOAUTH2"
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Attempt to authenticate
DEBUG SMTP: check mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM 
DEBUG SMTP: AUTH LOGIN command trace suppressed
DEBUG SMTP: AUTH LOGIN succeeded

これについてのあなたの考えを私に知らせてください、そしてこれに関するどんな助けも本当にありがたいです。

-ナレンドラ

4

5 に答える 5

27

どのようにメッセージを送信していますか?JavaMail FAQTransport.sendは、静的メソッドがメッセージごとに新しい接続を開くことを示唆しています。これは、適切なTransportインスタンスを作成し、接続し、呼び出しsendMessageてから、接続を再度閉じる便利なメソッドだからです。Transportから独自のインスタンスを取得する場合Sessionは、一度接続してから、繰り返し呼び出しsendMessageて1つの接続で複数のメッセージを送信し、最後にcloseそれを送信します。(未テスト)の線に沿った何か:

Transport t = session.getTransport();
t.connect();
try {
  for(Message m : messages) {
    m.saveChanges();
    t.sendMessage(m, m.getAllRecipients());
  }
} finally {
  t.close();
}

try withresourcesブロックを使用するように更新されました:

try (Transport t = session.getTransport()) {
    t.connect();
    for(Message m : messages) {
        m.saveChanges();
        t.sendMessage(m, m.getAllRecipients());
    }
}
于 2012-11-08T11:34:09.683 に答える
10

私は仕事で同じ要件を得ました。一括メールとスタンドアロンメールを送信する必要があります。単純で満足のいく答えは見つかりません。単一の接続を使用して一括メールを送信できますが、非同期バッファリングを作成してメールをバッチで送信するまで、スタンドアロンのメールは送信できません。

Transport大事なことを言い忘れましたが、短時間に多くの接続を使用するとno more socket handles are available、すべてのポートが状態のままになるため、につながる可能性がありTIME_WAITます。

私は最終的に、SMTP接続プールが最適であると結論付けました。ライブラリが存在しないため(少なくとも無料)、ApacheCommonPoolとJavaMailを使用して私のものを作成します。

//Declare the factory and the connection pool, usually at the application startup
SmtpConnectionPool smtpConnectionPool = new SmtpConnectionPool(SmtpConnectionFactoryBuilder.newSmtpBuilder().build());

//borrow an object in a try-with-resource statement or call `close` by yourself
try (ClosableSmtpConnection transport = smtpConnectionPool.borrowObject()) {
    MimeMessage mimeMessage = new MimeMessage(session);
    MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, false);
    mimeMessageHelper.addTo("to@example.com");
    mimeMessageHelper.setFrom("from@example.com");
    mimeMessageHelper.setSubject("Hi!");
    mimeMessageHelper.setText("Hello World!", false);
    transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
}

//Close the pool, usually when the application shutdown
smtpConnectionPool.close();
于 2015-05-15T14:33:29.153 に答える
1

上記の回答は、関連性がないか、実装するには複雑すぎます。だからここに私はSpringBootで大量のメールを送信するための最も簡単な解決策を投稿しています

使用するだけ

mimeMessageHelper.setBcc(emailList);

どこ、

mimeMessageHelperですMimeMessageHelperemailListですString[] emailList

ノート:

使用していないことを確認してください

mimeMessageHelper.setTo(emailList)

それ以外の場合は、受信者の受信メールにすべての受信者のメールアドレスが表示されます。

詳細については、これこれは、SpringBootでメールを送信する方法を学ぶのに役立ちます

于 2021-04-14T07:31:08.810 に答える
0

標準のJavaメールAPIで、実行しようとしていること(セッションの再利用)が許可されているかどうかはわかりませんが、マルチスレッドの使用を検討することはできます。

ThreadPoolを使用して、メール送信ジョブを送信します。次に、ThreadPoolによって非同期的に実行されるジョブクラスコード内でエラー処理/再送信を実行すると、メインスレッドは他のことを再開できます。ジョブの送信には数ミリ秒しかかかりません。Javaでスレッドプールを使って何かを実装してからしばらく経ちましたが、それはかなり簡単で簡単だったことを覚えています。あなたがグーグル「Javaスレッドプール」なら、あなたはたくさんの資料を見つけます。

于 2012-11-08T11:07:03.367 に答える
-1

非常に優れたパフォーマンスが得られるため、スレッドプールを使用できます。以下のコードスニペットを実装して共有しました。

try  {
    ExecutorService executor = Executors.newFixedThreadPool("no. of threads"); // no. of threads is depend on your cpu/memory usage it's better to test with diff. no. of threads.
    Runnable worker = new MyRunnable(message); // message is the javax.mail.Message
    executor.execute(worker);
    executor.shutdown();
    executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
}
于 2015-10-14T15:50:00.843 に答える