11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package org.openjdk.skara.email;
24
25 import java.io.*;
26 import java.net.Socket;
27 import java.nio.charset.StandardCharsets;
28 import java.time.Duration;
29 import java.time.format.DateTimeFormatter;
30 import java.util.regex.Pattern;
31
32 /**
33 * Limited SMTP client implementation - only compatibility requirement (currently) is the OpenJDK
34 * mailing list servers.
35 */
36 public class SMTP {
37 private static Pattern initReply = Pattern.compile("220 .*");
38 private static Pattern ehloReply = Pattern.compile("^250 .*");
39 private static Pattern mailReply = Pattern.compile("^250 .*");
40 private static Pattern rcptReply = Pattern.compile("^250 .*");
41 private static Pattern dataReply = Pattern.compile("354 Enter.*");
42 private static Pattern doneReply = Pattern.compile("250 .*");
43
44 public static void send(String server, EmailAddress recipient, Email email) throws IOException {
45 send(server, recipient, email, Duration.ofMinutes(30));
46 }
47
48 public static void send(String server, EmailAddress recipient, Email email, Duration timeout) throws IOException {
49 var port = 25;
50 if (server.contains(":")) {
51 var parts = server.split(":", 2);
52 server = parts[0];
53 port = Integer.parseInt(parts[1]);
54 }
55 try (var socket = new Socket(server, port);
56 var out = new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8);
57 var in = new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8)) {
58
59 var session = new SMTPSession(in, out, timeout);
60
61 session.waitForPattern(initReply);
62 session.sendCommand("EHLO " + email.sender().domain(), ehloReply);
63 session.sendCommand("MAIL FROM:" + email.sender().address(), mailReply);
64 session.sendCommand("RCPT TO:<" + recipient.address() + ">", rcptReply);
65 session.sendCommand("DATA", dataReply);
66 session.sendCommand("From: " + MimeText.encode(email.author().toString()));
67 session.sendCommand("Message-Id: " + email.id());
68 session.sendCommand("Date: " + email.date().format(DateTimeFormatter.RFC_1123_DATE_TIME));
69 session.sendCommand("Sender: " + MimeText.encode(email.sender().toString()));
70 session.sendCommand("To: " + MimeText.encode(recipient.toString()));
71 for (var header : email.headers()) {
72 session.sendCommand(header + ": " + MimeText.encode(email.headerValue(header)));
73 }
74 session.sendCommand("Subject: " + MimeText.encode(email.subject()));
75 session.sendCommand("Content-type: text/plain; charset=utf-8");
76 session.sendCommand("");
77 session.sendCommand(email.body());
78 session.sendCommand(".", doneReply);
79 session.sendCommand("QUIT");
80 }
81 }
82 }
|
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package org.openjdk.skara.email;
24
25 import java.io.*;
26 import java.net.Socket;
27 import java.nio.charset.StandardCharsets;
28 import java.time.Duration;
29 import java.time.format.DateTimeFormatter;
30 import java.util.regex.Pattern;
31 import java.util.stream.Collectors;
32
33 /**
34 * Limited SMTP client implementation - only compatibility requirement (currently) is the OpenJDK
35 * mailing list servers.
36 */
37 public class SMTP {
38 private static Pattern initReply = Pattern.compile("^220 .*");
39 private static Pattern ehloReply = Pattern.compile("^250 .*");
40 private static Pattern mailReply = Pattern.compile("^250 .*");
41 private static Pattern rcptReply = Pattern.compile("^250 .*");
42 private static Pattern dataReply = Pattern.compile("^354 .*");
43 private static Pattern doneReply = Pattern.compile("^250 .*");
44
45 public static void send(String server, EmailAddress recipient, Email email) throws IOException {
46 send(server, recipient, email, Duration.ofMinutes(30));
47 }
48
49 public static void send(String server, EmailAddress recipient, Email email, Duration timeout) throws IOException {
50 var port = 25;
51 if (server.contains(":")) {
52 var parts = server.split(":", 2);
53 server = parts[0];
54 port = Integer.parseInt(parts[1]);
55 }
56 try (var socket = new Socket(server, port);
57 var out = new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8);
58 var in = new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8)) {
59
60 var session = new SMTPSession(in, out, timeout);
61
62 session.waitForPattern(initReply);
63 session.sendCommand("EHLO " + email.sender().domain(), ehloReply);
64 session.sendCommand("MAIL FROM:" + email.sender().address(), mailReply);
65 session.sendCommand("RCPT TO:<" + recipient.address() + ">", rcptReply);
66 session.sendCommand("DATA", dataReply);
67 session.sendCommand("From: " + MimeText.encode(email.author().toString()));
68 session.sendCommand("Message-Id: " + email.id());
69 session.sendCommand("Date: " + email.date().format(DateTimeFormatter.RFC_1123_DATE_TIME));
70 session.sendCommand("Sender: " + MimeText.encode(email.sender().toString()));
71 session.sendCommand("To: " + MimeText.encode(recipient.toString()));
72 for (var header : email.headers()) {
73 session.sendCommand(header + ": " + MimeText.encode(email.headerValue(header)));
74 }
75 session.sendCommand("Subject: " + MimeText.encode(email.subject()));
76 session.sendCommand("Content-type: text/plain; charset=utf-8");
77 session.sendCommand("");
78 var escapedBody = email.body().lines()
79 .map(line -> line.startsWith(".") ? "." + line : line)
80 .collect(Collectors.joining("\n"));
81 session.sendCommand(escapedBody);
82 session.sendCommand(".", doneReply);
83 session.sendCommand("QUIT");
84 }
85 }
86 }
|