OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 149 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
144 ilm 1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
9
 * language governing permissions and limitations under the License.
10
 *
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
13
 
14
 package org.openconcerto.utils.io;
15
 
16
import org.openconcerto.utils.ExceptionUtils;
17
 
182 ilm 18
import java.util.Objects;
144 ilm 19
import java.util.Properties;
20
 
21
import javax.mail.Address;
22
import javax.mail.Message;
23
import javax.mail.MessagingException;
24
import javax.mail.PasswordAuthentication;
25
import javax.mail.SendFailedException;
26
import javax.mail.Transport;
182 ilm 27
import javax.mail.internet.AddressException;
28
import javax.mail.internet.InternetAddress;
144 ilm 29
 
30
/**
31
 * A mail account.
32
 *
33
 * @author Sylvain
34
 */
35
public class MailAccount {
36
 
37
    static public void addTimeouts(final Properties props, final String protocol) {
38
        // 3 minutes
39
        props.setProperty("mail." + protocol + ".connectiontimeout", "180000");
40
        props.setProperty("mail." + protocol + ".timeout", "180000");
41
        props.setProperty("mail." + protocol + ".writetimeout", "180000");
42
    }
43
 
44
    /**
149 ilm 45
     * Workaround for <code>ATT######.dat</code> attachments.
46
     *
47
     * @param props must currently be {@link System#getProperties()}.
48
     */
49
    static public final void setEncodedParametersForOutlook(final Properties props) {
50
        // don't use RFC 2231 for all parameters for 2 reasons :
51
        // 1. Outlook (at least 2007) doesn't support it. Thunderbird seems to get around this by
52
        // encoding the filename of Content-Disposition according to RFC 2231 and also encoding it
53
        // in Content-Type using the old de facto standard.
54
        // 2. Java Mail 1.6.0 doesn't always use Parameter Value Continuations (not for filenames :
55
        // javax.mail.internet.MimeBodyPart.setFileName() uses ParameterList.Value which isn't
56
        // split by toString())
57
        // used in ParameterList.encodeParameters
58
        props.setProperty("mail.mime.encodeparameters", "false");
59
        // since we don't use RFC 2231, use the old de facto standard to have a charset specified
60
        // somewhere.
61
        // used in MimeBodyPart.encodeFileName
62
        props.setProperty("mail.mime.encodefilename", "true");
63
    }
64
 
65
    /**
144 ilm 66
     * Parse the given exception to a more human readable format.
67
     *
68
     * @param mex an exception.
69
     * @return some useful informations.
70
     */
71
    public static final String handle(MessagingException mex) {
72
        final StringBuilder sb = new StringBuilder(512);
73
        sb.append(ExceptionUtils.getStackTrace(mex) + "\n");
74
        Exception ex = mex;
75
        do {
76
            if (ex instanceof SendFailedException) {
77
                SendFailedException sfex = (SendFailedException) ex;
78
                Address[] invalid = sfex.getInvalidAddresses();
79
                if (invalid != null) {
80
                    sb.append("    ** Invalid Addresses\n");
81
                    if (invalid != null) {
82
                        for (int i = 0; i < invalid.length; i++)
83
                            sb.append("         " + invalid[i]);
84
                    }
85
                }
86
                Address[] validUnsent = sfex.getValidUnsentAddresses();
87
                if (validUnsent != null) {
88
                    sb.append("    ** ValidUnsent Addresses\n");
89
                    if (validUnsent != null) {
90
                        for (int i = 0; i < validUnsent.length; i++)
91
                            sb.append("         " + validUnsent[i]);
92
                    }
93
                }
94
                Address[] validSent = sfex.getValidSentAddresses();
95
                if (validSent != null) {
96
                    sb.append("    ** ValidSent Addresses\n");
97
                    if (validSent != null) {
98
                        for (int i = 0; i < validSent.length; i++)
99
                            sb.append("         " + validSent[i]);
100
                    }
101
                }
102
            }
103
            sb.append("\n");
104
            if (ex instanceof MessagingException)
105
                ex = ((MessagingException) ex).getNextException();
106
            else
107
                ex = null;
108
        } while (ex != null);
109
 
110
        return sb.toString();
111
    }
112
 
182 ilm 113
    public static final MailAccount create(final String fromAddr, String smtpServer, String smtpLogin, String smtpPassword) throws AddressException {
114
        Objects.requireNonNull(fromAddr, "Missing 'From:' address");
115
        final InternetAddress fromInetAddr = new InternetAddress(fromAddr, true);
116
        if (smtpServer == null) {
117
            smtpServer = "smtp." + fromInetAddr.getAddress().substring(fromInetAddr.getAddress().indexOf('@') + 1);
118
        }
119
        if (smtpLogin == null) {
120
            smtpLogin = fromInetAddr.getAddress().substring(0, fromInetAddr.getAddress().indexOf('@'));
121
        }
122
        final MailAccount res = new MailAccount(fromInetAddr.getPersonal(), fromInetAddr.getAddress(), smtpServer);
123
        res.setAuth(new PasswordAuthentication(smtpLogin, smtpPassword));
124
        return res;
125
    }
126
 
144 ilm 127
    // nullable
128
    private final String name;
129
    private final String address;
130
    private final String smtpServer;
131
    private final int port;
132
    private PasswordAuthentication auth;
133
 
134
    /**
135
     * Create a new account.
136
     *
137
     * @param name the personal name, e.g. "J. Smith", can be <code>null</code>.
138
     * @param address the email, e.g. "j.smith@foo.com".
139
     * @param smtpServer the SMTP server.
140
     */
141
    public MailAccount(String name, String address, String smtpServer) {
142
        this(name, address, smtpServer, -1);
143
    }
144
 
145
    public MailAccount(String name, String address, String smtpServer, int port) {
146
        super();
147
        this.name = name;
148
        this.address = address;
149
        this.smtpServer = smtpServer;
150
        this.port = port;
151
        this.auth = null;
152
    }
153
 
154
    public final String getName() {
155
        return this.name;
156
    }
157
 
158
    public final String getAddress() {
159
        return this.address;
160
    }
161
 
162
    public final String getSMTPServer() {
163
        return this.smtpServer;
164
    }
165
 
166
    public final int getPort() {
167
        return this.port;
168
    }
169
 
170
    public final PasswordAuthentication getAuth() {
171
        return this.auth;
172
    }
173
 
174
    public void setAuth(PasswordAuthentication auth) {
175
        this.auth = auth;
176
    }
177
 
178
    public String getSMTPProtocol() {
179
        return "smtp";
180
    }
181
 
182
    public final Properties createProperties() {
183
        return this.createProperties(false);
184
    }
185
 
186
    public final Properties createProperties(final boolean trustServer) {
187
        final Properties props = new Properties();
188
        final String proto = getSMTPProtocol();
189
        props.setProperty("mail.transport.protocol", proto);
190
        final String prefix = "mail." + proto + ".";
191
        props.setProperty(prefix + "host", this.getSMTPServer());
192
        props.setProperty(prefix + "port", this.getPort() < 0 ? "587" : String.valueOf(this.getPort()));
193
        props.setProperty(prefix + "starttls.required", "true");
194
        if (trustServer)
195
            props.setProperty(prefix + "ssl.trust", this.getSMTPServer());
196
        addTimeouts(props, proto);
197
        return props;
198
    }
199
 
200
    public final void send(final Message msg) throws MessagingException {
201
        final PasswordAuthentication auth = this.getAuth();
182 ilm 202
        final Properties props = msg.getSession().getProperties();
203
        props.setProperty("mail." + getSMTPProtocol() + ".auth", auth == null ? "false" : "true");
144 ilm 204
        try (final Transport mailTransport = msg.getSession().getTransport()) {
205
            if (auth == null)
206
                mailTransport.connect();
207
            else
208
                mailTransport.connect(auth.getUserName(), auth.getPassword());
209
            mailTransport.sendMessage(msg, msg.getAllRecipients());
182 ilm 210
        } catch (MessagingException e) {
211
            throw new MessagingException("Couldn't send as " + auth.getUserName() + " using\n" + props, e);
144 ilm 212
        }
213
    }
214
 
215
    @Override
216
    public String toString() {
217
        return this.getClass().getSimpleName() + " " + getAddress() + " through " + this.getSMTPServer();
218
    }
219
}