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 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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