# Viele verschiedene E-Mails an unterschiedliche Empfänger schnell versenden?



## Bergtroll (9. Dez 2011)

Hallo mal wieder, liebes Forum,

ich stehe gerade vor der Frage, wie ich für unser aktuelles Projekt den Mailversand organisiere. Ich habe mit JavaMail und meinem Mailaccount gespielt und das hat auch geklappt, allerdings dauert der Versandprozess 2 Sekunden, was viel zu lange den Thread blockiert. Größter Teil davon ist so das Drumherumreden der Protokolle und Verbindungsaufbau. Klar der läuft in eigenem Prozess, der Mailinput kommt asynchron per ZeroMQ. Aber ich frage mich trotzdem, ob das so lange dauer muss, schließlich sollen eine ganze Menge Mails versandt werden... 

Ich dachte jetzt, vielleicht wirds schneller, wenn man nen lokalen Exim oder so installiert der erstmal sammelt. Aber muss nicht auch lokal ne Verbindung aufgebaut werden, was dann genauso lange dauert? Gibts einen Low Level weg die E-Mails an Exim zu geben? Denke ich zu kompliziert? Oder doch lieber Amazon Cloud Simple Mail Service? Ganz was anderes? Wie ist denn bei euch der Mailversand in größeren Mengen realisiert?

Viele Grüße,

Bergtroll


----------



## irgendjemand (9. Dez 2011)

interessant wäre vielleicht mal der code mit dem du deine mails versendest ..
wenn du schon selbst sagst das es prob mail 2 sec dauert und das viel außenrum geschiet ... würde ich fast vermuten das du die static methode Transport.send(Message) callst ...
der api ist zu entnehmen das diese methode selbstständig alle verbindungs-daten handelt ... also auch jedesmal ne verbindung aufbaut ... die mail sendet ... und die verbindung wieder abbaut ...

alternativ kann es auch daran liegen wie du den content zusammenbaust und wie viel es überhaupt pro mail ist ...

ein sehr einfaches tutorial : E-Mails mit JavaMail versenden @ tutorials.de: Tutorials, Forum & Hilfe

wie hier zu sehen ist wird die verbindung VOR dem senden aufgebaut ... dann die mail versendet ... und dann die verbindung erst abgebaut ...

angenommen die mails sind vorher schon zusammengebaut ... brauchst du nur noch Transport.sendMessage(Message, Address[]) in einem loop zu callen

alternativ kannst du auch mehrere empfänger gleichzeitig angeben ... sendest also nur eine mail und dein provider erledigt den rest ...

aber wie gesgt : ohne code kann man dem problem nicht auf die spur kommen


----------



## homer65 (9. Dez 2011)

Die Frage ist auch über wen du deine Mails versenden willst.
Wenn du kostenlose Anbieter nutzt, wirst du mit diversen Einschränkungen leben müssen.
Es könnte durchaus sein, das der Anbieter den du nutzt absichtlich den Verbindungsaufbau verzögert.


----------



## Bergtroll (9. Dez 2011)

Guten Morgen, erst einmal vielen Dank für die Antworten. Also ich versende über Googlemail, wollte ja erstmal nur testen. Für den Produktiveinsatz überlegen ich entweder einen Mailserver aufzusetzen. Davor habe ich aber gehörigen Respekt, weil man offensichtlich viel falsch machen kann und schnell geblacklistet wird. Oder eben einen Service zu nutzen. Aber erstmal würde ich halt ganz gerne auf meiner Seite sicherstellen, dass schnelle viele Mails rausgegeben werden können. Ich hatte auch gedacht, man könne ja vielleicht eine Verbindung dauerhaft offenhalten, aber entweder habe ich das falsch verstanden oder SMTP sieht das nicht vor? Jetzt erstmal der Testcode. Nicht über das DEBUG Flag wundern, damit dauerts sogar noch länger aber so sieht man wenigstens was passiert:


```
import java.util.Properties;

import javax.mail.Address;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;

import com.sun.mail.smtp.SMTPMessage;

public class SendMailTest {

	private static final String SMTP_HOST_NAME = "smtp.gmail.com";
	private static final int SMTP_HOST_PORT = 465;
	private static final String SMTP_AUTH_USER = "myaddress@gmail.com";
	private static final String SMTP_AUTH_PWD = "mypassword";

	private final Session session;
	private final Transport transport;

	public SendMailTest() {
		this.session = this.createSession();
		this.transport = this.createTransport();
	}

	private Session createSession() {
		Properties properties = this.createProperties();
		Session session = Session.getDefaultInstance(properties);
		session.setDebug(true);
		return session;
	}

	private Properties createProperties() {
		Properties properties = new Properties();
		properties.put("mail.transport.protocol", "smtps");
		properties.put("mail.smtps.host", SMTP_HOST_NAME);
		properties.put("mail.smtps.auth", "true");
		properties.put("mail.smtp.from", SMTP_AUTH_USER);
		return properties;
	}

	private Transport createTransport() {
		Transport transport = null;
		try {
			transport = this.session.getTransport();
		} catch (NoSuchProviderException e) {
			e.printStackTrace();
		}
		return transport;
	}

	public static void main(String[] args) {
		SendMailTest mailer = new SendMailTest();
		InternetAddress mailto;
		try {
			mailto = new InternetAddress("recipient@example.com");
			mailer.sendMail(mailto, "SSL Test", "This is an SMTPS SSL connection testmail");
		} catch (AddressException e) {
			e.printStackTrace();
		}
	}

	public void sendMail(Address toAddress, String subject, String content) {
		SMTPMessage message = createMessage(subject, content);
		System.out.println("EMAIL TEST: " + message.toString());
		try {
			transport.connect(SMTP_HOST_NAME, SMTP_HOST_PORT, SMTP_AUTH_USER,
					SMTP_AUTH_PWD);
			transport.sendMessage(message, new Address[] { toAddress });
		} catch (MessagingException e) {
			e.printStackTrace();
		}
	}

	private SMTPMessage createMessage(String subject, String content) {
		SMTPMessage message = new SMTPMessage(session);
		try {
			message.setSubject(subject);
			message.setContent(content, "text/plain");
		} catch (MessagingException e) {
			e.printStackTrace();
		}
		return message;
	}
}
```


----------



## irgendjemand (9. Dez 2011)

mal davon abgesehen das in deinem beispiel das Transport.close() vollständig fehlt hast du meinen post scheinbar nicht ganz verstanden

dein problem ist das du jedes mal bevor du eine mail sendest eine neue verbindung aufbaust ...

wenn du viele mails nach ein ander senden willst musst du aber unabhängig von deiner sendMail-methode die verbindung manager ... also von außen noch zwei methoden ala open() und close() und diese um den for()-loop legen der die mails rausjagd

wenn ich meinen code von tut.de entsprechend verändere


```
transport.connect(host, port, user, pass);
for(int i=0; i<mails.length; i++)
{
	transport.sendMessage(mails[i].getMessage(), mails[i].getAddresses());
	System.out.println("SEND");
}
transport.close();
```

kann ich mit g-mail locker 100 mails an einem stück versenden ohne das ich ich die verbindung jedes mal neu aufbauen muss ...

mails[] ist hierbei ein array der klasse Mail welche mir über zwei getter einmal die Message und zum anderen das Address[] array liefert um mails und adressen synchron zu halten ... müsstest du eventuell selbst bauen ...

da ich nur relativ geringen upload habe *384kBit/s* dauern 100 mails natürlich etwas ... aber wenn ich die zeit durch 100 teile komme ich auf unter 2sec / mail ...

von daher bestätigt sich hier nur meine anfangsvermutung : ansatt EINE verbindung für alle mails zu nutzen baust du jedes mal für eine neue mail auch eine neue verbindung auf ...


----------



## Bergtroll (9. Dez 2011)

Erst einmal vielen Dank für das Feedback, habe die Schleife eingebaut und bei mir funktionierts jetzt auch besser... Bis auf, dass E-Mails von googlemail nicht bei web.de ankommen...



irgendjemand hat gesagt.:


> mal davon abgesehen das in deinem beispiel das Transport.close() vollständig fehlt (...)



Oh danke, das scheine ich beim refaktorieren aus Versehen gekillt zu haben. Das kommt davon, wen man sich beim Ausprobieren kein Unit tests schreibt, die schauen, ob alles sauber geschlossen wird . Ich werde mich besser!!! 




irgendjemand hat gesagt.:


> hast du meinen post scheinbar nicht ganz verstanden. dein problem ist das du jedes mal bevor du eine mail sendest eine neue verbindung aufbaust ...



Doch ich hatte deinen Post schon verstanden, aber ich hatte ein Problem mit dem Protokoll. Ich habe z.B. den Wiki Artikel gelesen Simple Mail Transfer Protocol ? Wikipedia und die ersten paar RFCs zumindest quergelesen. Überall sieht SMTP so aus, als wäre es wie HTTP ein Ablauf der immer aus 


```
CONNECT -> DATENAUSTAUSCH -> DISCONNECT
```

besteht. Und zwar für jede E-Mail einzeln. Soweit ich das gelesen habe, habe ich nicht gesehen, dass in SMTP so etwas definiert ist: 


```
CONNECT -> DATENAUSTAUSCH MAIL 1 -> ... -> DATENAUSTAUSCH MAIL N  -> DISCONNECT.
```

Aber damit wäre ja das Verhalten, mit JavaMail die Connection offen zu halten, undefiniert und ich könnte mich nicht darauf verlassen, dass es immer läuft? Oder verstehe ich das ganze falsch? Hat SMTP vielleicht garnix mit dem Connection Aufbau an sich zu tun?


----------



## irgendjemand (9. Dez 2011)

ich weis zwar nicht welche RFCs du dir angesehen hast ... oder welche teile davon ... aber du hast da irgendwas missverstanden ...

wenn du nach meinem beispiel oben eine verbindung zum SMTP-server aufbaust ... dich authtifizierst ... dann wartet der SMTP server auf befehle ... und zwar so lange du ihn nicht per ausdrücklichem befehl dazu veranlasst die verbindung zu trennen ...
heißt also : so lange du den server hintereinander weg mit send-mail-commandos fütterst ... so lange nimmt er auch die e-mails an und speichert sie erstmal zwischen ...

wann und wie der SMTP-server die e-mails aus deinem konto weiter an die empfänger leitest kannst du als client nicht beeinflussen ...

aber anzunehmen das du für jede e-mail immer wieder eine neue verbindung brauchen würdest ... das stimmt nicht ... du kannst eine verbindung für mehrere e-mails verwenden ...

genau wie beim abrufen von mails mit POP3 ... da hast du auch eine verbindung für mehr als eine e-mail ...


ob die mails überhaupt von deinem rechner bei google ankommen kannst du bei google irgendwo unter postausgang oder gesendet oder so nachsehen ... dort sollten die e-mails die du via SMTP verschickt hast noch mal als kopie auftauchen ...

das es aber dauert von googlemail zu anderen providern zu schicken liegt daran das google die e-mails erstmal als kopie auf seine server zieht ... steht auch irgendwo in den AGB das die das ganz legal machen ... es kann auch sein wenn du zu viele mails an einen bestimmten empfänger schicken willst das das n timelimit hat ... auch kann es sein das web.de das ganze blockt ... vllt mal im spam-ordner nachgucken ...


was aber auf jeden geht : mit hilfe von g-mail mehrere mails über EINE verbindung an web.de zu schicken *selbst getestet*


----------



## Bergtroll (9. Dez 2011)

Cool, vielen lieben Dank für die Klarstellung, dann habe ich den Teil tatsächlich falsch verstanden. D.H. ich kann mir eine Verbindung offen halten, die zum Beispiel erst dicht macht, wenn 2 Minuten nix mehr Neues kommt oder so :toll: .

Das bei Web.de nix ankommt, scheint irgendein anderes Problem zu sein. Habe festgestellt, dass nicht mal E-Mails, die ich manuell über Weboberfläche abschicke, dort ankommen... auch nicht im SPAM... komisch...

Schönes Wochenende


----------



## irgendjemand (9. Dez 2011)

so stimmt das auch nicht ...
also ein gewisses timeout hat die verbindung natürlich auch ...
irgendwann ist die warterei dem smtp-server auch zu viel und er beendet die verbindung ...

also einfach verbindung offenhalt nur um dann mal alle paar minuten ne mail zu senden ... das geht so leider auch nicht ...

du kannst aber , wenn du bereits mehrere mails generiert und zwischengespeichert hast , diese über eine verbindung hintereinander weg senden ... und solltest danach aber die verbindung auch wieder schließen

das du von g-mail gar keine mails empfängst ist komisch ...

wenn ich das ganze als beispiel mit 1 mail mache ... und diese auch wie JavaMail von web.de abholen will ist diese nach knapp 10sec-20sec da ... keine probleme ...

musst mal in web.de unter EINSTELLUNGEN und dann sowas wie REGELN *habs nich genau im kopf* nach sehen ... dort stehen deine ganze blockier und sonst-was listen ... vllt steckt da der fehler ...


----------

