Mit Java eine E-Mail versenden

Häufig steht man bei Webprojekten vor der Anforderung E-Mails zu versenden, zum Beispiel für Bestellbestätigungen, das Versenden von Login Informationen oder Newslettern. In einem kleinen Beispiel werde ich zeigen, wie man sich eine Klasse schreibt, von der man in seiner ganzen Webanwendung aus E-Mail versenden kann. Damit das Versenden der E-Mail sich nicht bei der Antwortzeit des Benutzers bemerkbar macht, z.B. durch den Aufbau der Verbindung zum E-Mail Server, werden wir das Versenden der E-Mail asynchron ausführen. Als erstes ladet ihr euch das JavaMail Paket und das Activation Paket von Sun herunter, die darin enthaltenen Dateien mail.jar und activation.jar packt ihr in euer WEB-INF/lib Verzeichnis. Wir benötigen für dieses Beispiel drei Klassen. Als erstes eine Klasse Mail die unsere eigentliche E-Mail repräsentiert.
import java.util.List;
 
public class Mail
{
  private String    sender, to, bcc, cc, subject, text;
  private List< MailAnhang >        anhaenge;
 
  public Mail(String sender, String to, String subject, String text)
  {
    super();
    this.sender = sender;
    this.to = to;
    this.subject = subject;
    this.text = text;
  }
 
  public List< MailAnhang >; getAnhaenge()
  {
     return anhaenge;
  }
 
  public String getBcc()
  {
    return bcc;
  }
 
  public String getCc()
  {
    return cc;
  }
 
  public String getSender()
  {
    return sender;
  }
 
  public String getSubject()
  {
    return subject;
  }
 
  public String getText()
  {
    return text;
  }
 
  public String getTo()
  {
    return to;
  }
 
  public void setAnhaenge(List< MailAnhang > anhaenge)
  {
    this.anhaenge = anhaenge;
  }
 
  public void setBcc(String bcc)
  {
    this.bcc = bcc;
  }
 
  public void setCc(String cc)
  {
    this.cc = cc;
  }
 
  public void setSender(String sender)
  {
    this.sender = sender;
  }
 
  public void setSubject(String subject)
  {
    this.subject = subject;
  }
 
  public void setText(String text)
  {
    this.text = text;
  }
 
  public void setTo(String to)
  {
    this.to = to;
  }
}
Und die Klasse MailAnhang, falls man zum Beispiel eine Rechnung versenden will.
import java.io.File;
 
public class MailAnhang
{
  private String name;
  private String mime;
  private File      file;
 
  public MailAnhang(String name, String mime, File file)
  {
    super();
    this.name = name;
    this.mime = mime;
    this.file = file;
  }
 
  public String getName()
  {
    return name;
  }
 
  public String getMime()
  {
    return mime;
  }
 
  public File getFile()
  {
    return file;
  }
}
Jetzt kommen wir zu der Klasse MailSender, die unsere E-Mail versenden wird. Damit es diesen Dienst in unsere Anwendung nur einmal gibt, ist das Ganze als Singleton implementiert. Die Mails werden durch die Methode sendMail(Mail m) unserer Liste übergeben. Und dieses List wird zyklisch von einem separaten Thread überprüft, ob es neue Einträge gibt.
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
 
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.util.ByteArrayDataSource;
 
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
 
public class MailSender
{
  private static final Log    log    = LogFactory.getLog(MailSender.class);
  private InternetAddress     addressFrom;
  private InternetAddress     addressTo;
  private InternetAddress     addressCc;
  private InternetAddress     addressBcc;
  private MimeMessage         msg;
  private MimeMultipart       content;
  private Session             session;
  private Transport           transport;
  private Properties          props           = new Properties();
  private String              smtpHost        = "deinesmtphost.de";
  private String              smtpBenutzer    = "benutzer";
  private String              smtpPasswort    = "passwort";
  private int                 counter         = 0;
 
  /** Die MailQueue hier werden die Mail abgelegt bevor Sie asynchron versendet werden */
  private LinkedList    mailQueue;
 
  /** Privates Klassenattribut, einzige Instanz der Klasse wird erzeugt. */
  private static final MailSender    INSTANCE    = new MailSender();
 
  /**
  * Statische Methode "getInstance()" liefert die einzige Instanz der Klasse
  * zurück. Dadurch gibt es nur eine zentrale Instance in der Webanwendung die E-Mails versendet.
  */
  public static MailSender getInstance()
  {
    return INSTANCE;
  }
 
  /** Konstruktor ist privat, darf nicht von außen instanziert werden. */
  private MailSender()
  {
    mailQueue = new LinkedList();
    props.put("mail.smtp.host", smtpHost);
    this.counter = 0;
    session = Session.getDefaultInstance(props, null);
    try
    {
      transport = session.getTransport("smtp");
    }
    catch (Exception e)
    {
      log.error("Fehler beim initialisieren der Klasse : " + e, e);
    }
    Thread m = new Thread(new Mailer());
    m.start();
  }
 
  /** Übergeben der E-Mail an die MailQueue*/
  public boolean sendMail(Mail m)
  {
    try
    {
      mailQueue.add(m);
      return true;
    }
    catch (Exception e)
    {
      return false;
    }
  }
 
  /** Der Mailer versendet Die E-Mails im asynchron im Hintergrund als eigener Thread */
  private class Mailer extends Thread
  {
    int                        threadnummer;
 
    Mailer()
    {
      super();
    }
 
    @Override
    public void run()
    {
      // Endlosschleife zum zyklischen überprüfen ob neue Mails zum versenden vorhanden sind
      while (true)
      {
	try
	{
	  //Sind neue Mails vorhanden?
	  if (!mailQueue.isEmpty())
	  {
	    //Die erste Mail aus der Queue holen
	    Mail m = mailQueue.removeFirst();
	    try
	    {
	      content = new MimeMultipart("alternativ");
	      msg = new MimeMessage(session);
 
	      //Die Adresse des Versenders
	      addressFrom = new InternetAddress(m.getSender());
	      msg.setFrom(addressFrom);
 
	      //Die Adresse des Empfängers
	      addressTo = new InternetAddress(m.getTo());
	      msg.addRecipient(Message.RecipientType.TO, addressTo);
 
	      //Die Adresse des Kopieemfängers
	      if (m.getCc() != null &amp;&amp; m.getCc().length() &gt; 3)
	      {
		addressCc = new InternetAddress(m.getCc());
		msg.addRecipient(Message.RecipientType.CC, addressCc);
	      }
 
	      //Die Adresse des Blindkopieempfängers
	      if (m.getBcc() != null &amp;&amp; m.getBcc().length() &gt; 3)
	      {
		addressBcc = new InternetAddress(m.getBcc());
		msg.addRecipient(Message.RecipientType.BCC, addressBcc);
	      }
 
	      //Der Betreff
	      msg.setSubject(m.getSubject());
 
	      //Der eigentliche Text im HTML Format
	      MimeBodyPart text = new MimeBodyPart();
	      text.setContent(m.getText(), "text/html");
	      content.addBodyPart(text);
 
	      //Die Anhänge
	      List< MailAnhang > dateien = m.getAnhaenge();
	      if(dateien != null)
	      {
		for (MailAnhang mailAnhang : dateien)
		{
		  BodyPart anhang = new MimeBodyPart();
		  anhang.setFileName(mailAnhang.getName());
		  InputStream is = new FileDataSource(mailAnhang.getFile()).getInputStream();
		  DataSource dh = new ByteArrayDataSource(is, mailAnhang.getMime());
		  anhang.setDataHandler(new DataHandler(dh));
		  content.addBodyPart(anhang);
		}
	      }
 
	      //Setzen des Content
	      msg.setContent(content);
	      msg.saveChanges();
	      transport = session.getTransport("smtp");
 
	      //Verbindung zu Mailserver aufbauen
	      transport.connect(smtpHost, smtpBenutzer, smtpPasswort);
	      transport.sendMessage(msg, msg.getAllRecipients());
	      transport.close();
	      counter++;
	      if (log.isDebugEnabled()) log.debug("Mail " + counter + " " + m.getSubject() + " erfolgreich gesendet");
	    }
	    catch (MessagingException me)
	    {
	      log.error("Fehler beim Versenden der Mail : " + me, me);
	    }
	    catch (Exception e)
	    {
	      log.error("Fehler beim Versenden der Mail : " + e, e);
	    }
	  }
	  else
	  {
	      //Alle wieviel Minuten soll die Queue auf neue Mails überprüft und diese versendet werden.
	      Thread.sleep(600l);
	  }
	}
	catch (Exception e)
	{
	  log.error("Fehler beim Versenden der Mail : " + e, e);
	}
      }
    }
  }
}
Um jetzt eine Mail zu versenden, brauchen wir in unserer Webanwendung nur noch folgenden Code aufrufen.
Mail m = new Mail("empfaenger@domain.de", "versender@domain.de" , "Mein Betreff", "Und hier der <strong>Text</strong> der versendet wird.");
List<mailanhang> anhang = new LinkedList</mailanhang><mailanhang>();
anhang.add(new MailAnhang("PDF Rechnung", "application/pdf", pdfFile));
m.setAnhaenge(anhang);
MailServer.getInstance().sendMail(m);</mailanhang>

3 Comments

  1. Christian Ullenboom

    Eine Alternative bietet http://commons.apache.org/email/ — das sieht dann so ähnlich aus. Christian

    Reply
  2. Jan H

    Moin, in der Klasse “Mail” – “public void setAnhaenge(List; anhaenge)” Ich denke mal ein Semikolon zu viel .-) Klasse “MailSender” unter “Die Anhänge” – “for (MailAnhang mailAnhang : dateien)” Netbeans zeigt mir dort ein Typenkonflikt an (ObjektListe). Ein Fehler? Wie lautet es richtig? Mit Gruß

    PS: Hoffentlich nun mit richtiger Anzeigeformatierung .-)

    Reply
    1. jogep (Post author)

      Danke für die Fehlermeldung, ich habe den Code gleich mal korrigiert.
      Entweder du nutzt Generics die seit Java 5 verfügbar sind. Oder Du musst die Objecte in der Liste noch auf MailAnhang casten.

      Reply

Leave a Reply