X-Git-Url: http://jaekl.net/gitweb/?p=cfb.git;a=blobdiff_plain;f=prod%2Fnet%2Fjaekl%2Fqd%2Futil%2FSendMail.java;h=33be358b31edc0c28e7b232861e89419a76357ca;hp=ce21ea3ba81538694d250b3820b8d98463fa5067;hb=04db511351db70ea603cb65f3f2c5c0b7462d9cc;hpb=c0bde8e3268a2f1ba05166b174a0d733237dc246 diff --git a/prod/net/jaekl/qd/util/SendMail.java b/prod/net/jaekl/qd/util/SendMail.java index ce21ea3..33be358 100644 --- a/prod/net/jaekl/qd/util/SendMail.java +++ b/prod/net/jaekl/qd/util/SendMail.java @@ -3,10 +3,13 @@ package net.jaekl.qd.util; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -17,8 +20,17 @@ public class SendMail { private static final String RESP_251 = "251"; // mail address change (we don't support this) private static final String RESP_354 = "354"; // OK, proceed with DATA transmission + // Actually, RFC821 (with which all SMTP should be backwards-compatible) + // requires all control transmissions to be done in US-ASCII. + // However, there's no point in throwing an exception if the server with which + // we're communicating sends bytes with the high bit set. So, let's read from + // the socket with the only Charset that Java guarantees will be available that + // can also read arbitrary sequences of 8-bit bytes. + private static final String SMTP_CHARSET = "ISO-8859-1"; + String m_hostName; String m_boundary; + Charset m_charset; String m_smtpHost; int m_smtpPort; @@ -55,9 +67,9 @@ public class SendMail { public void send() throws MailException { try ( - Socket sock = new Socket(m_smtpHost, m_smtpPort); - PrintWriter pw = new PrintWriter(sock.getOutputStream(), true); - BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream())); + Socket sock = openSocket(m_smtpHost, m_smtpPort); + PrintWriter pw = new PrintWriter(new OutputStreamWriter(sock.getOutputStream(), StandardCharsets.US_ASCII), true); + BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream(), getCharset())); ) { send(pw, br); @@ -67,6 +79,10 @@ public class SendMail { } } + Socket openSocket(String host, int port) throws UnknownHostException, IOException { + return new Socket(host, port); + } + String getHostName() throws UnknownHostException { if (null == m_hostName) { m_hostName = InetAddress.getLocalHost().getHostName(); @@ -84,6 +100,7 @@ public class SendMail { validateResponse("", RESP_220, line); cmd = "HELO " + getHostName(); + line = sendLine(pw, br, cmd); validateResponse(cmd, RESP_250, line); cmd = "MAIL FROM: " + m_from; @@ -124,14 +141,14 @@ public class SendMail { sendMimeParts(pw); - String result = sendLine(pw, br, "\r\n.\r\n"); + String result = sendLine(pw, br, "\r\n."); return result; } void sendMimeHeaders(PrintWriter pw) { sendLine(pw, "MIME-Version: 1.0"); - sendLine(pw, "Content-Type: multipart/mixed; boundary=" + getBoundary()); + sendLine(pw, "Content-Type: multipart/mixed; boundary=\"" + getBoundary() + "\""); } void sendMimeParts(PrintWriter pw) { @@ -140,6 +157,7 @@ public class SendMail { sendLine(pw, "Content-Type: " + part.getMimeType()); // TODO: Add support for encodings sendLine(pw, ""); sendLine(pw, part.getContent()); + sendLine(pw, ""); } sendLine(pw, "--" + getBoundary() + "--"); } @@ -153,6 +171,13 @@ public class SendMail { return true; } + Charset getCharset() { + if (null == m_charset) { + m_charset = Charset.forName(SMTP_CHARSET); + } + return m_charset; + } + String getBoundary() { if (null != m_boundary) { @@ -188,7 +213,7 @@ public class SendMail { } } - void validateResponse(String cmd, String actual, String expected) throws MailException + void validateResponse(String cmd, String expected, String actual) throws MailException { if (! actual.startsWith(expected)) { throw new MailException(cmd, expected, actual); @@ -280,6 +305,7 @@ public class SendMail { void sendLine(PrintWriter pw, String line) { pw.write(line + "\r\n"); + pw.flush(); } String sendLine(PrintWriter pw, BufferedReader br, String line) throws IOException