Dépôt officiel du code source de l'ERP OpenConcerto
Rev 149 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.utils.io;
import org.openconcerto.utils.ExceptionUtils;
import java.util.Objects;
import java.util.Properties;
import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.SendFailedException;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
/**
* A mail account.
*
* @author Sylvain
*/
public class MailAccount {
static public void addTimeouts(final Properties props, final String protocol) {
// 3 minutes
props.setProperty("mail." + protocol + ".connectiontimeout", "180000");
props.setProperty("mail." + protocol + ".timeout", "180000");
props.setProperty("mail." + protocol + ".writetimeout", "180000");
}
/**
* Workaround for <code>ATT######.dat</code> attachments.
*
* @param props must currently be {@link System#getProperties()}.
*/
static public final void setEncodedParametersForOutlook(final Properties props) {
// don't use RFC 2231 for all parameters for 2 reasons :
// 1. Outlook (at least 2007) doesn't support it. Thunderbird seems to get around this by
// encoding the filename of Content-Disposition according to RFC 2231 and also encoding it
// in Content-Type using the old de facto standard.
// 2. Java Mail 1.6.0 doesn't always use Parameter Value Continuations (not for filenames :
// javax.mail.internet.MimeBodyPart.setFileName() uses ParameterList.Value which isn't
// split by toString())
// used in ParameterList.encodeParameters
props.setProperty("mail.mime.encodeparameters", "false");
// since we don't use RFC 2231, use the old de facto standard to have a charset specified
// somewhere.
// used in MimeBodyPart.encodeFileName
props.setProperty("mail.mime.encodefilename", "true");
}
/**
* Parse the given exception to a more human readable format.
*
* @param mex an exception.
* @return some useful informations.
*/
public static final String handle(MessagingException mex) {
final StringBuilder sb = new StringBuilder(512);
sb.append(ExceptionUtils.getStackTrace(mex) + "\n");
Exception ex = mex;
do {
if (ex instanceof SendFailedException) {
SendFailedException sfex = (SendFailedException) ex;
Address[] invalid = sfex.getInvalidAddresses();
if (invalid != null) {
sb.append(" ** Invalid Addresses\n");
if (invalid != null) {
for (int i = 0; i < invalid.length; i++)
sb.append(" " + invalid[i]);
}
}
Address[] validUnsent = sfex.getValidUnsentAddresses();
if (validUnsent != null) {
sb.append(" ** ValidUnsent Addresses\n");
if (validUnsent != null) {
for (int i = 0; i < validUnsent.length; i++)
sb.append(" " + validUnsent[i]);
}
}
Address[] validSent = sfex.getValidSentAddresses();
if (validSent != null) {
sb.append(" ** ValidSent Addresses\n");
if (validSent != null) {
for (int i = 0; i < validSent.length; i++)
sb.append(" " + validSent[i]);
}
}
}
sb.append("\n");
if (ex instanceof MessagingException)
ex = ((MessagingException) ex).getNextException();
else
ex = null;
} while (ex != null);
return sb.toString();
}
public static final MailAccount create(final String fromAddr, String smtpServer, String smtpLogin, String smtpPassword) throws AddressException {
Objects.requireNonNull(fromAddr, "Missing 'From:' address");
final InternetAddress fromInetAddr = new InternetAddress(fromAddr, true);
if (smtpServer == null) {
smtpServer = "smtp." + fromInetAddr.getAddress().substring(fromInetAddr.getAddress().indexOf('@') + 1);
}
if (smtpLogin == null) {
smtpLogin = fromInetAddr.getAddress().substring(0, fromInetAddr.getAddress().indexOf('@'));
}
final MailAccount res = new MailAccount(fromInetAddr.getPersonal(), fromInetAddr.getAddress(), smtpServer);
res.setAuth(new PasswordAuthentication(smtpLogin, smtpPassword));
return res;
}
// nullable
private final String name;
private final String address;
private final String smtpServer;
private final int port;
private PasswordAuthentication auth;
/**
* Create a new account.
*
* @param name the personal name, e.g. "J. Smith", can be <code>null</code>.
* @param address the email, e.g. "j.smith@foo.com".
* @param smtpServer the SMTP server.
*/
public MailAccount(String name, String address, String smtpServer) {
this(name, address, smtpServer, -1);
}
public MailAccount(String name, String address, String smtpServer, int port) {
super();
this.name = name;
this.address = address;
this.smtpServer = smtpServer;
this.port = port;
this.auth = null;
}
public final String getName() {
return this.name;
}
public final String getAddress() {
return this.address;
}
public final String getSMTPServer() {
return this.smtpServer;
}
public final int getPort() {
return this.port;
}
public final PasswordAuthentication getAuth() {
return this.auth;
}
public void setAuth(PasswordAuthentication auth) {
this.auth = auth;
}
public String getSMTPProtocol() {
return "smtp";
}
public final Properties createProperties() {
return this.createProperties(false);
}
public final Properties createProperties(final boolean trustServer) {
final Properties props = new Properties();
final String proto = getSMTPProtocol();
props.setProperty("mail.transport.protocol", proto);
final String prefix = "mail." + proto + ".";
props.setProperty(prefix + "host", this.getSMTPServer());
props.setProperty(prefix + "port", this.getPort() < 0 ? "587" : String.valueOf(this.getPort()));
props.setProperty(prefix + "starttls.required", "true");
if (trustServer)
props.setProperty(prefix + "ssl.trust", this.getSMTPServer());
addTimeouts(props, proto);
return props;
}
public final void send(final Message msg) throws MessagingException {
final PasswordAuthentication auth = this.getAuth();
final Properties props = msg.getSession().getProperties();
props.setProperty("mail." + getSMTPProtocol() + ".auth", auth == null ? "false" : "true");
try (final Transport mailTransport = msg.getSession().getTransport()) {
if (auth == null)
mailTransport.connect();
else
mailTransport.connect(auth.getUserName(), auth.getPassword());
mailTransport.sendMessage(msg, msg.getAllRecipients());
} catch (MessagingException e) {
throw new MessagingException("Couldn't send as " + auth.getUserName() + " using\n" + props, e);
}
}
@Override
public String toString() {
return this.getClass().getSimpleName() + " " + getAddress() + " through " + this.getSMTPServer();
}
}