it-swarm.com.de

Wie kann ich Massenmails mit der javax.mail API effizient versenden? & Können wir authentifizierte Sitzungen wiederverwenden, um die Geschwindigkeit zu verbessern?

Ich kann eine E-Mail mit der javax.mail-API senden. Das Problem hierbei ist jedoch, dass durchschnittlich 4,3 Sekunden benötigt werden, um eine E-Mail an das Ziel zu senden.

Wenn ich nacheinander 20 Mails versende, dauert es ungefähr 86.599 Sekunden. Für meine Anforderung wird dieser Ansatz nicht funktionieren. Ich suche einen Ansatz, mit dem ich in kürzerer Zeit eine große Anzahl von Mails verschicken kann.

Wenn ich mir das Debug-Protokoll anschaue, versucht die API, sich für jede gesendete Nachricht beim SMTP-Server zu authentifizieren. Ich erstelle jedoch nur eine Sitzung und verwende dieselbe Sitzung für alle von mir gesendeten E-Mails. Jetzt ist meine Frage, ob es nicht jedes Mal ein Overhead-Prozess ist, wenn er sich beim SMTP-Server authentifiziert. Gibt es keinen besseren Ansatz?

Unten finden Sie die Protokollablaufverfolgung, die Sie möglicherweise hilfreich finden.

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

Bitte teilen Sie mir Ihre Gedanken dazu mit und jede Hilfe hierzu wird sehr geschätzt.

-Narendra

16
Narendra

Wie senden Sie die Nachrichten? Die JavaMail FAQ schlägt vor, dass die statische Transport.send -Methode eine neue Verbindung für jede Nachricht öffnet, da es sich um eine praktische Methode handelt, die eine geeignete Transport -Instanz erstellt, diese verbindet, sendMessage aufruft und dann die schließt Verbindung wieder. Wenn Sie Ihre eigene Transport -Instanz aus der Session erhalten, können Sie eine Verbindung einmal herstellen, dann rufen Sie sendMessage wiederholt auf, um mehrere Nachrichten auf einer Verbindung zu senden, und schließlich close. Etwas in der Art von (ungetestet):

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

Ich habe die gleiche Anforderung bei der Arbeit. Ich muss Bulk-E-Mails und eigenständige E-Mails senden. Ich finde keine einfache und zufriedenstellende Antwort: Massen-E-Mails können über eine einzige Verbindung gesendet werden, Standalone-E-Mails jedoch erst, wenn eine asynchrone Pufferung zum Senden von E-Mails im Batch erstellt wurde.

Last but not least kann die Verwendung vieler Transport-Verbindungen in kurzer Zeit zu einem no more socket handles are available führen, da alle Ports im TIME_WAIT-Status hängen bleiben.

Ich komme zu dem Schluss, dass das Beste ein SMTP-Verbindungspool ist und weil keine Bibliothek existiert (zumindest kostenlos) ich erstelle meine mit Apache Common Pool und Java Mail:

//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("[email protected]");
    mimeMessageHelper.setFrom("[email protected]");
    mimeMessageHelper.setSubject("Hi!");
    mimeMessageHelper.setText("Hello World!", false);
    transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
}

//Close the pool, usually when the application shutdown
smtpConnectionPool.close();
11
Nicolas Labrot

Keine Ahnung, ob die Standard-Java-Mail-API zulässt, was Sie erreichen möchten (Wiederverwendung von Sitzungen), aber Sie können die Verwendung von Multithreading in Betracht ziehen:

Ich würde einen ThreadPool verwenden und E-Mail-Sendeaufträge an ihn senden. Anschließend führen Sie eine Fehlerbehandlung/erneutes Senden innerhalb des Jobklassencodes durch, der vom ThreadPool asynchron ausgeführt wird, und Ihr Hauptthread kann wieder andere Aufgaben ausführen. Das Senden eines Auftrags dauert nur Millisekunden. Es ist schon eine Weile her, dass ich etwas mit Thread-Pools in Java implementiert habe, aber ich erinnere mich, dass es ziemlich einfach und unkompliziert war. Wenn Sie "Java ThreadPool" googeln, finden Sie reichlich Material.

1
FelixD

Sie können Thread-Pooling verwenden, da es eine sehr gute Leistung bietet. Ich habe das folgende Code-Snippet implementiert und teile es Ihnen.

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);
}
0
S Boot