forked from I2P_Developers/i2p.i2p
* SusiMail:
- Use pipelining in SMTP - Rewrite SMTP response processing - Translate SMTP error messages - Right-justify msg size in folder view - String.compareTo() cleanup
This commit is contained in:
@@ -415,10 +415,10 @@ public class WebMail extends HttpServlet
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( mailPart.multipart ) {
|
if( mailPart.multipart ) {
|
||||||
if( mailPart.type.compareTo( "multipart/alternative" ) == 0 ) {
|
if( mailPart.type.equals("multipart/alternative")) {
|
||||||
MailPart chosen = null;
|
MailPart chosen = null;
|
||||||
for( MailPart subPart : mailPart.parts ) {
|
for( MailPart subPart : mailPart.parts ) {
|
||||||
if( subPart.type != null && subPart.type.compareTo( "text/plain" ) == 0 )
|
if( subPart.type != null && subPart.type.equals("text/plain"))
|
||||||
chosen = subPart;
|
chosen = subPart;
|
||||||
}
|
}
|
||||||
if( chosen != null ) {
|
if( chosen != null ) {
|
||||||
@@ -454,7 +454,7 @@ public class WebMail extends HttpServlet
|
|||||||
showBody = true;
|
showBody = true;
|
||||||
}
|
}
|
||||||
if( showBody == false && mailPart.type != null ) {
|
if( showBody == false && mailPart.type != null ) {
|
||||||
if( mailPart.type.compareTo( "text/plain" ) == 0 ) {
|
if( mailPart.type.equals("text/plain")) {
|
||||||
showBody = true;
|
showBody = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -559,7 +559,7 @@ public class WebMail extends HttpServlet
|
|||||||
String pop3Port = request.getParameter( POP3 );
|
String pop3Port = request.getParameter( POP3 );
|
||||||
String smtpPort = request.getParameter( SMTP );
|
String smtpPort = request.getParameter( SMTP );
|
||||||
String fixedPorts = Config.getProperty( CONFIG_PORTS_FIXED, "true" );
|
String fixedPorts = Config.getProperty( CONFIG_PORTS_FIXED, "true" );
|
||||||
if( fixedPorts.compareToIgnoreCase( "false" ) != 0 ) {
|
if( !fixedPorts.equalsIgnoreCase("false")) {
|
||||||
host = Config.getProperty( CONFIG_HOST, DEFAULT_HOST );
|
host = Config.getProperty( CONFIG_HOST, DEFAULT_HOST );
|
||||||
pop3Port = Config.getProperty( CONFIG_PORTS_POP3, "" + DEFAULT_POP3PORT );
|
pop3Port = Config.getProperty( CONFIG_PORTS_POP3, "" + DEFAULT_POP3PORT );
|
||||||
smtpPort = Config.getProperty( CONFIG_PORTS_SMTP, "" + DEFAULT_SMTPPORT );
|
smtpPort = Config.getProperty( CONFIG_PORTS_SMTP, "" + DEFAULT_SMTPPORT );
|
||||||
@@ -885,7 +885,7 @@ public class WebMail extends HttpServlet
|
|||||||
private static int getCheckedMessage(RequestWrapper request) {
|
private static int getCheckedMessage(RequestWrapper request) {
|
||||||
for( Enumeration<String> e = request.getParameterNames(); e.hasMoreElements(); ) {
|
for( Enumeration<String> e = request.getParameterNames(); e.hasMoreElements(); ) {
|
||||||
String parameter = e.nextElement();
|
String parameter = e.nextElement();
|
||||||
if( parameter.startsWith( "check" ) && request.getParameter( parameter ).compareTo( "1" ) == 0 ) {
|
if( parameter.startsWith( "check" ) && request.getParameter( parameter ).equals("1")) {
|
||||||
String number = parameter.substring( 5 );
|
String number = parameter.substring( 5 );
|
||||||
try {
|
try {
|
||||||
int n = Integer.parseInt( number );
|
int n = Integer.parseInt( number );
|
||||||
@@ -972,7 +972,7 @@ public class WebMail extends HttpServlet
|
|||||||
else if( sessionObject.attachments != null && buttonPressed( request, DELETE_ATTACHMENT ) ) {
|
else if( sessionObject.attachments != null && buttonPressed( request, DELETE_ATTACHMENT ) ) {
|
||||||
for( Enumeration<String> e = request.getParameterNames(); e.hasMoreElements(); ) {
|
for( Enumeration<String> e = request.getParameterNames(); e.hasMoreElements(); ) {
|
||||||
String parameter = e.nextElement();
|
String parameter = e.nextElement();
|
||||||
if( parameter.startsWith( "check" ) && request.getParameter( parameter ).compareTo( "1" ) == 0 ) {
|
if( parameter.startsWith( "check" ) && request.getParameter( parameter ).equals("1")) {
|
||||||
String number = parameter.substring( 5 );
|
String number = parameter.substring( 5 );
|
||||||
try {
|
try {
|
||||||
int n = Integer.parseInt( number );
|
int n = Integer.parseInt( number );
|
||||||
@@ -1119,7 +1119,7 @@ public class WebMail extends HttpServlet
|
|||||||
if( buttonPressed( request, REALLYDELETE ) ) {
|
if( buttonPressed( request, REALLYDELETE ) ) {
|
||||||
for( Enumeration<String> e = request.getParameterNames(); e.hasMoreElements(); ) {
|
for( Enumeration<String> e = request.getParameterNames(); e.hasMoreElements(); ) {
|
||||||
String parameter = e.nextElement();
|
String parameter = e.nextElement();
|
||||||
if( parameter.startsWith( "check" ) && request.getParameter( parameter ).compareTo( "1" ) == 0 ) {
|
if( parameter.startsWith( "check" ) && request.getParameter( parameter ).equals("1")) {
|
||||||
String number = parameter.substring( 5 );
|
String number = parameter.substring( 5 );
|
||||||
try {
|
try {
|
||||||
int n = Integer.parseInt( number );
|
int n = Integer.parseInt( number );
|
||||||
@@ -1170,11 +1170,11 @@ public class WebMail extends HttpServlet
|
|||||||
{
|
{
|
||||||
String str = request.getParameter( sort_id );
|
String str = request.getParameter( sort_id );
|
||||||
if( str != null ) {
|
if( str != null ) {
|
||||||
if( str.compareToIgnoreCase( "up" ) == 0 ) {
|
if( str.equalsIgnoreCase("up")) {
|
||||||
sessionObject.folder.setSortingDirection( Folder.UP );
|
sessionObject.folder.setSortingDirection( Folder.UP );
|
||||||
sessionObject.folder.sortBy( sort_id );
|
sessionObject.folder.sortBy( sort_id );
|
||||||
}
|
}
|
||||||
if( str.compareToIgnoreCase( "down" ) == 0 ) {
|
if( str.equalsIgnoreCase("down")) {
|
||||||
sessionObject.folder.setSortingDirection( Folder.DOWN );
|
sessionObject.folder.setSortingDirection( Folder.DOWN );
|
||||||
sessionObject.folder.sortBy( sort_id );
|
sessionObject.folder.sortBy( sort_id );
|
||||||
}
|
}
|
||||||
@@ -1471,7 +1471,7 @@ public class WebMail extends HttpServlet
|
|||||||
|
|
||||||
String prop = Config.getProperty( CONFIG_SENDER_FIXED, "true" );
|
String prop = Config.getProperty( CONFIG_SENDER_FIXED, "true" );
|
||||||
String domain = Config.getProperty( CONFIG_SENDER_DOMAIN, "mail.i2p" );
|
String domain = Config.getProperty( CONFIG_SENDER_DOMAIN, "mail.i2p" );
|
||||||
if( prop.compareToIgnoreCase( "false" ) != 0 ) {
|
if( !prop.equalsIgnoreCase("false")) {
|
||||||
from = "<" + sessionObject.user + "@" + domain + ">";
|
from = "<" + sessionObject.user + "@" + domain + ">";
|
||||||
}
|
}
|
||||||
ArrayList<String> toList = new ArrayList<String>();
|
ArrayList<String> toList = new ArrayList<String>();
|
||||||
@@ -1503,7 +1503,7 @@ public class WebMail extends HttpServlet
|
|||||||
|
|
||||||
String bccToSelf = request.getParameter( NEW_BCC_TO_SELF );
|
String bccToSelf = request.getParameter( NEW_BCC_TO_SELF );
|
||||||
|
|
||||||
if( bccToSelf != null && bccToSelf.compareTo( "1" ) == 0 )
|
if( bccToSelf != null && bccToSelf.equals("1"))
|
||||||
recipients.add( sender );
|
recipients.add( sender );
|
||||||
|
|
||||||
if( toList.isEmpty() ) {
|
if( toList.isEmpty() ) {
|
||||||
@@ -1619,7 +1619,7 @@ public class WebMail extends HttpServlet
|
|||||||
String from = request.getParameter( NEW_FROM );
|
String from = request.getParameter( NEW_FROM );
|
||||||
String fixed = Config.getProperty( CONFIG_SENDER_FIXED, "true" );
|
String fixed = Config.getProperty( CONFIG_SENDER_FIXED, "true" );
|
||||||
|
|
||||||
if( from == null || fixed.compareToIgnoreCase( "false" ) != 0 ) {
|
if( from == null || !fixed.equalsIgnoreCase("false")) {
|
||||||
String domain = Config.getProperty( CONFIG_SENDER_DOMAIN, "mail.i2p" );
|
String domain = Config.getProperty( CONFIG_SENDER_DOMAIN, "mail.i2p" );
|
||||||
from = "<" + sessionObject.user + "@" + domain + ">";
|
from = "<" + sessionObject.user + "@" + domain + ">";
|
||||||
}
|
}
|
||||||
@@ -1637,12 +1637,12 @@ public class WebMail extends HttpServlet
|
|||||||
|
|
||||||
out.println( "<table cellspacing=\"0\" cellpadding=\"5\">\n" +
|
out.println( "<table cellspacing=\"0\" cellpadding=\"5\">\n" +
|
||||||
"<tr><td colspan=\"2\" align=\"center\"><hr></td></tr>\n" +
|
"<tr><td colspan=\"2\" align=\"center\"><hr></td></tr>\n" +
|
||||||
"<tr><td align=\"right\">" + _("From:") + "</td><td align=\"left\"><input type=\"text\" size=\"80\" name=\"" + NEW_FROM + "\" value=\"" + from + "\" " + ( fixed.compareToIgnoreCase( "false" ) != 0 ? "disabled" : "" ) +"></td></tr>\n" +
|
"<tr><td align=\"right\">" + _("From:") + "</td><td align=\"left\"><input type=\"text\" size=\"80\" name=\"" + NEW_FROM + "\" value=\"" + from + "\" " + ( !fixed.equalsIgnoreCase("false") ? "disabled" : "" ) +"></td></tr>\n" +
|
||||||
"<tr><td align=\"right\">" + _("To:") + "</td><td align=\"left\"><input type=\"text\" size=\"80\" name=\"" + NEW_TO + "\" value=\"" + to + "\"></td></tr>\n" +
|
"<tr><td align=\"right\">" + _("To:") + "</td><td align=\"left\"><input type=\"text\" size=\"80\" name=\"" + NEW_TO + "\" value=\"" + to + "\"></td></tr>\n" +
|
||||||
"<tr><td align=\"right\">" + _("Cc:") + "</td><td align=\"left\"><input type=\"text\" size=\"80\" name=\"" + NEW_CC + "\" value=\"" + cc + "\"></td></tr>\n" +
|
"<tr><td align=\"right\">" + _("Cc:") + "</td><td align=\"left\"><input type=\"text\" size=\"80\" name=\"" + NEW_CC + "\" value=\"" + cc + "\"></td></tr>\n" +
|
||||||
"<tr><td align=\"right\">" + _("Bcc:") + "</td><td align=\"left\"><input type=\"text\" size=\"80\" name=\"" + NEW_BCC + "\" value=\"" + bcc + "\"></td></tr>\n" +
|
"<tr><td align=\"right\">" + _("Bcc:") + "</td><td align=\"left\"><input type=\"text\" size=\"80\" name=\"" + NEW_BCC + "\" value=\"" + bcc + "\"></td></tr>\n" +
|
||||||
"<tr><td align=\"right\">" + _("Subject:") + "</td><td align=\"left\"><input type=\"text\" size=\"80\" name=\"" + NEW_SUBJECT + "\" value=\"" + subject + "\"></td></tr>\n" +
|
"<tr><td align=\"right\">" + _("Subject:") + "</td><td align=\"left\"><input type=\"text\" size=\"80\" name=\"" + NEW_SUBJECT + "\" value=\"" + subject + "\"></td></tr>\n" +
|
||||||
"<tr><td> </td><td align=\"left\"><input type=\"checkbox\" class=\"optbox\" name=\"" + NEW_BCC_TO_SELF + "\" value=\"1\"" + ( bccToSelf.compareToIgnoreCase( "false" ) != 0 ? "checked" : "" )+ ">" + _("Bcc to self") + "</td></tr>\n" +
|
"<tr><td> </td><td align=\"left\"><input type=\"checkbox\" class=\"optbox\" name=\"" + NEW_BCC_TO_SELF + "\" value=\"1\"" + ( !bccToSelf.equalsIgnoreCase("false") ? "checked" : "" )+ ">" + _("Bcc to self") + "</td></tr>\n" +
|
||||||
"<tr><td colspan=\"2\" align=\"center\"><textarea cols=\"" + Config.getProperty( CONFIG_COMPOSER_COLS, 80 )+ "\" rows=\"" + Config.getProperty( CONFIG_COMPOSER_ROWS, 10 )+ "\" name=\"" + NEW_TEXT + "\">" + text + "</textarea>" +
|
"<tr><td colspan=\"2\" align=\"center\"><textarea cols=\"" + Config.getProperty( CONFIG_COMPOSER_COLS, 80 )+ "\" rows=\"" + Config.getProperty( CONFIG_COMPOSER_ROWS, 10 )+ "\" name=\"" + NEW_TEXT + "\">" + text + "</textarea>" +
|
||||||
"<tr><td colspan=\"2\" align=\"center\"><hr></td></tr>\n" +
|
"<tr><td colspan=\"2\" align=\"center\"><hr></td></tr>\n" +
|
||||||
"<tr><td align=\"right\">" + _("New Attachment:") + "</td><td align=\"left\"><input type=\"file\" size=\"50%\" name=\"" + NEW_FILENAME + "\" value=\"\"><input type=\"submit\" name=\"" + NEW_UPLOAD + "\" value=\"" + _("Upload File") + "\"></td></tr>" );
|
"<tr><td align=\"right\">" + _("New Attachment:") + "</td><td align=\"left\"><input type=\"file\" size=\"50%\" name=\"" + NEW_FILENAME + "\" value=\"\"><input type=\"submit\" name=\"" + NEW_UPLOAD + "\" value=\"" + _("Upload File") + "\"></td></tr>" );
|
||||||
@@ -1668,7 +1668,7 @@ public class WebMail extends HttpServlet
|
|||||||
private static void showLogin( PrintWriter out )
|
private static void showLogin( PrintWriter out )
|
||||||
{
|
{
|
||||||
String fixedPorts = Config.getProperty( CONFIG_PORTS_FIXED, "true" );
|
String fixedPorts = Config.getProperty( CONFIG_PORTS_FIXED, "true" );
|
||||||
boolean fixed = fixedPorts.compareToIgnoreCase( "false" ) != 0;
|
boolean fixed = !fixedPorts.equalsIgnoreCase("false");
|
||||||
String host = Config.getProperty( CONFIG_HOST, DEFAULT_HOST );
|
String host = Config.getProperty( CONFIG_HOST, DEFAULT_HOST );
|
||||||
String pop3 = Config.getProperty( CONFIG_PORTS_POP3, "" + DEFAULT_POP3PORT );
|
String pop3 = Config.getProperty( CONFIG_PORTS_POP3, "" + DEFAULT_POP3PORT );
|
||||||
String smtp = Config.getProperty( CONFIG_PORTS_SMTP, "" + DEFAULT_SMTPPORT );
|
String smtp = Config.getProperty( CONFIG_PORTS_SMTP, "" + DEFAULT_SMTPPORT );
|
||||||
@@ -1747,7 +1747,7 @@ public class WebMail extends HttpServlet
|
|||||||
boolean idChecked = false;
|
boolean idChecked = false;
|
||||||
String checkId = sessionObject.pageChanged ? null : request.getParameter( "check" + i );
|
String checkId = sessionObject.pageChanged ? null : request.getParameter( "check" + i );
|
||||||
|
|
||||||
if( checkId != null && checkId.compareTo( "1" ) == 0 )
|
if( checkId != null && checkId.equals("1"))
|
||||||
idChecked = true;
|
idChecked = true;
|
||||||
|
|
||||||
if( sessionObject.markAll )
|
if( sessionObject.markAll )
|
||||||
@@ -1765,7 +1765,7 @@ public class WebMail extends HttpServlet
|
|||||||
( idChecked ? "checked" : "" ) + ">" + "</td><td>" +
|
( idChecked ? "checked" : "" ) + ">" + "</td><td>" +
|
||||||
link + mail.shortSender + "</a></td><td> </td><td>" + link + mail.shortSubject + "</a></td><td> </td><td>" +
|
link + mail.shortSender + "</a></td><td> </td><td>" + link + mail.shortSubject + "</a></td><td> </td><td>" +
|
||||||
// don't let date get split across lines
|
// don't let date get split across lines
|
||||||
mail.localFormattedDate.replace(" ", " ") + "</td><td> </td><td>" +
|
mail.localFormattedDate.replace(" ", " ") + "</td><td> </td><td align=\"right\">" +
|
||||||
DataHelper.formatSize2(mail.size) + "B</td></tr>" );
|
DataHelper.formatSize2(mail.size) + "B</td></tr>" );
|
||||||
bg = 1 - bg;
|
bg = 1 - bg;
|
||||||
i++;
|
i++;
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
package i2p.susi.webmail.smtp;
|
package i2p.susi.webmail.smtp;
|
||||||
|
|
||||||
import i2p.susi.debug.Debug;
|
import i2p.susi.debug.Debug;
|
||||||
|
import i2p.susi.webmail.Messages;
|
||||||
import i2p.susi.webmail.encoding.Encoding;
|
import i2p.susi.webmail.encoding.Encoding;
|
||||||
import i2p.susi.webmail.encoding.EncodingException;
|
import i2p.susi.webmail.encoding.EncodingException;
|
||||||
import i2p.susi.webmail.encoding.EncodingFactory;
|
import i2p.susi.webmail.encoding.EncodingFactory;
|
||||||
@@ -32,6 +33,10 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.i2p.data.DataHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author susi
|
* @author susi
|
||||||
@@ -42,6 +47,7 @@ public class SMTPClient {
|
|||||||
private final byte buffer[];
|
private final byte buffer[];
|
||||||
public String error;
|
public String error;
|
||||||
private String lastResponse;
|
private String lastResponse;
|
||||||
|
private boolean supportsPipelining;
|
||||||
|
|
||||||
private static final Encoding base64;
|
private static final Encoding base64;
|
||||||
|
|
||||||
@@ -72,61 +78,126 @@ public class SMTPClient {
|
|||||||
* @since 0.9.13
|
* @since 0.9.13
|
||||||
*/
|
*/
|
||||||
private int sendCmd(String cmd, boolean shouldWait)
|
private int sendCmd(String cmd, boolean shouldWait)
|
||||||
|
{
|
||||||
|
if( socket == null )
|
||||||
|
return 0;
|
||||||
|
try {
|
||||||
|
if (cmd != null)
|
||||||
|
sendCmdNoWait(cmd);
|
||||||
|
if (!shouldWait)
|
||||||
|
return 100;
|
||||||
|
socket.getOutputStream().flush();
|
||||||
|
return getResult();
|
||||||
|
} catch (IOException e) {
|
||||||
|
error += "IOException occured.<br>";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does not flush, wait, or read
|
||||||
|
*
|
||||||
|
* @param cmd non-null
|
||||||
|
* @since 0.9.13
|
||||||
|
*/
|
||||||
|
private void sendCmdNoWait(String cmd) throws IOException
|
||||||
{
|
{
|
||||||
Debug.debug( Debug.DEBUG, "SMTP sendCmd(" + cmd +")" );
|
Debug.debug( Debug.DEBUG, "SMTP sendCmd(" + cmd +")" );
|
||||||
|
|
||||||
if( socket == null )
|
if( socket == null )
|
||||||
return 0;
|
throw new IOException("no socket");
|
||||||
|
OutputStream out = socket.getOutputStream();
|
||||||
int result = 0;
|
cmd += "\r\n";
|
||||||
lastResponse = "";
|
out.write( cmd.getBytes() );
|
||||||
|
}
|
||||||
try {
|
|
||||||
InputStream in = socket.getInputStream();
|
/**
|
||||||
OutputStream out = socket.getOutputStream();
|
* Pipeline if supported
|
||||||
|
*
|
||||||
if( cmd != null ) {
|
* @param cmds non-null
|
||||||
cmd += "\r\n";
|
* @return number of successful commands
|
||||||
out.write( cmd.getBytes() );
|
* @since 0.9.13
|
||||||
}
|
*/
|
||||||
if (!shouldWait)
|
private int sendCmds(List<SendExpect> cmds)
|
||||||
return 100;
|
{
|
||||||
out.flush();
|
int rv = 0;
|
||||||
String str = "";
|
if (supportsPipelining) {
|
||||||
boolean doContinue = true;
|
Debug.debug(Debug.DEBUG, "SMTP pipelining " + cmds.size() + " commands");
|
||||||
while( doContinue ) {
|
try {
|
||||||
if( in.available() > 0 ) {
|
for (SendExpect cmd : cmds) {
|
||||||
int read = in.read( buffer );
|
sendCmdNoWait(cmd.send);
|
||||||
str += new String( buffer, 0, read );
|
|
||||||
lastResponse += str;
|
|
||||||
while( true ) {
|
|
||||||
int i = str.indexOf( "\r\n" );
|
|
||||||
if( i == -1 )
|
|
||||||
break;
|
|
||||||
if( result == 0 ) {
|
|
||||||
try {
|
|
||||||
result = Integer.parseInt( str.substring( 0, 3 ) );
|
|
||||||
}
|
|
||||||
catch( NumberFormatException nfe ) {
|
|
||||||
result = 0;
|
|
||||||
doContinue = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if( str.substring( 3, 4 ).compareTo( " " ) == 0 ) {
|
|
||||||
doContinue = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
str = str.substring( i + 2 );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
socket.getOutputStream().flush();
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
for (SendExpect cmd : cmds) {
|
||||||
|
int r = getResult();
|
||||||
|
// stop only on EOF
|
||||||
|
if (r == 0)
|
||||||
|
break;
|
||||||
|
if (r == cmd.expect)
|
||||||
|
rv++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (SendExpect cmd : cmds) {
|
||||||
|
int r = sendCmd(cmd.send);
|
||||||
|
// stop at first error
|
||||||
|
if (r != cmd.expect)
|
||||||
|
break;
|
||||||
|
rv++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
Debug.debug(Debug.DEBUG, "SMTP success in " + rv + " of " + cmds.size() + " commands");
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return result code or 0 for failure
|
||||||
|
* @since 0.9.13
|
||||||
|
*/
|
||||||
|
private int getResult() {
|
||||||
|
return getFullResult().result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return result code and string, all lines combined with \r separators,
|
||||||
|
* first 3 bytes are the ASCII return code or "000" for failure
|
||||||
|
* Result and Result.recv non null
|
||||||
|
* @since 0.9.13
|
||||||
|
*/
|
||||||
|
private Result getFullResult() {
|
||||||
|
int result = 0;
|
||||||
|
StringBuilder fullResponse = new StringBuilder(512);
|
||||||
|
try {
|
||||||
|
InputStream in = socket.getInputStream();
|
||||||
|
StringBuilder buf = new StringBuilder(128);
|
||||||
|
while (DataHelper.readLine(in, buf)) {
|
||||||
|
Debug.debug(Debug.DEBUG, "SMTP rcv \"" + buf.toString().trim() + '"');
|
||||||
|
int len = buf.length();
|
||||||
|
if (len < 4) {
|
||||||
|
result = 0;
|
||||||
|
break; // huh? no nnn\r?
|
||||||
|
}
|
||||||
|
if( result == 0 ) {
|
||||||
|
try {
|
||||||
|
String r = buf.substring(0, 3);
|
||||||
|
result = Integer.parseInt(r);
|
||||||
|
} catch ( NumberFormatException nfe ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fullResponse.append(buf.substring(4));
|
||||||
|
if (buf.charAt(3) == ' ')
|
||||||
|
break;
|
||||||
|
buf.setLength(0);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
error += "IOException occured.<br>";
|
error += "IOException occured.<br>";
|
||||||
result = 0;
|
result = 0;
|
||||||
}
|
}
|
||||||
return result;
|
lastResponse = fullResponse.toString();
|
||||||
|
return new Result(result, lastResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -139,60 +210,118 @@ public class SMTPClient {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
socket = new Socket( host, port );
|
socket = new Socket( host, port );
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch (Exception e) {
|
error += _("Cannot connect") + ": " + e.getMessage() + "<br>";
|
||||||
error += "Cannot connect: " + e.getMessage() + "<br>";
|
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if( ok && sendCmd( null ) == 220 &&
|
// SMTP ref: RFC 821
|
||||||
sendCmd( "EHLO localhost" ) == 250 &&
|
// Pipelining ref: RFC 2920
|
||||||
sendCmd( "AUTH LOGIN" ) == 334 &&
|
// AUTH ref: RFC 4954
|
||||||
sendCmd( base64.encode( user ) ) == 334 &&
|
if (ok) {
|
||||||
sendCmd( base64.encode( pass ) ) == 235 &&
|
int result = sendCmd(null);
|
||||||
sendCmd( "MAIL FROM: " + sender ) == 250 ) {
|
if (result != 220) {
|
||||||
|
error += _("Server refused connection") + " (" + result + ")<br>";
|
||||||
for( int i = 0; i < recipients.length; i++ ) {
|
ok = false;
|
||||||
if( sendCmd( "RCPT TO: " + recipients[i] ) != 250 ) {
|
|
||||||
ok = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if( ok ) {
|
|
||||||
if( sendCmd( "DATA" ) == 354 ) {
|
|
||||||
if( body.indexOf( "\r\n.\r\n" ) != -1 )
|
|
||||||
body = body.replaceAll( "\r\n.\r\n", "\r\n..\r\n" );
|
|
||||||
body += "\r\n.\r\n";
|
|
||||||
try {
|
|
||||||
socket.getOutputStream().write( body.getBytes() );
|
|
||||||
if( sendCmd( null ) == 250 ) {
|
|
||||||
mailSent = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
ok = false;
|
|
||||||
error += "Error while sending mail: " + e.getMessage() + "<br>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ok) {
|
||||||
|
sendCmdNoWait( "EHLO localhost" );
|
||||||
|
socket.getOutputStream().flush();
|
||||||
|
Result r = getFullResult();
|
||||||
|
if (r.result == 250) {
|
||||||
|
supportsPipelining = r.recv.contains("PIPELINING");
|
||||||
|
} else {
|
||||||
|
error += _("Server refused connection") + " (" + r.result + ")<br>";
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ok) {
|
||||||
|
// RFC 4954 says AUTH must be the last but let's assume
|
||||||
|
// that includes the user/pass on following lines
|
||||||
|
List<SendExpect> cmds = new ArrayList<SendExpect>();
|
||||||
|
cmds.add(new SendExpect("AUTH LOGIN", 334));
|
||||||
|
cmds.add(new SendExpect(base64.encode(user), 334));
|
||||||
|
cmds.add(new SendExpect(base64.encode(pass), 235));
|
||||||
|
if (sendCmds(cmds) != 3) {
|
||||||
|
error += _("Login failed") + "<br>";
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ok) {
|
||||||
|
List<SendExpect> cmds = new ArrayList<SendExpect>();
|
||||||
|
cmds.add(new SendExpect("MAIL FROM: " + sender, 250));
|
||||||
|
for( int i = 0; i < recipients.length; i++ ) {
|
||||||
|
cmds.add(new SendExpect("RCPT TO: " + recipients[i], 250));
|
||||||
|
}
|
||||||
|
cmds.add(new SendExpect("DATA", 354));
|
||||||
|
if (sendCmds(cmds) != cmds.size()) {
|
||||||
|
// TODO which recipient?
|
||||||
|
error += _("Mail rejected") + "<br>";
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ok) {
|
||||||
|
if( body.indexOf( "\r\n.\r\n" ) != -1 )
|
||||||
|
body = body.replaceAll( "\r\n.\r\n", "\r\n..\r\n" );
|
||||||
|
socket.getOutputStream().write( body.getBytes() );
|
||||||
|
socket.getOutputStream().write("\r\n.\r\n".getBytes() );
|
||||||
|
int result = sendCmd(null);
|
||||||
|
if (result == 250)
|
||||||
|
mailSent = true;
|
||||||
|
else
|
||||||
|
error += _("Error sending mail") + " (" + result + ")<br>";
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
error += _("Error sending mail") + ": " + e.getMessage() + "<br>";
|
||||||
|
|
||||||
} catch (EncodingException e) {
|
} catch (EncodingException e) {
|
||||||
ok = false;
|
|
||||||
error += e.getMessage();
|
error += e.getMessage();
|
||||||
}
|
}
|
||||||
if( !mailSent && lastResponse.length() > 0 ) {
|
if( !mailSent && lastResponse.length() > 0 ) {
|
||||||
String[] lines = lastResponse.split( "\r\n" );
|
String[] lines = lastResponse.split( "\r" );
|
||||||
for( int i = 0; i < lines.length; i++ )
|
for( int i = 0; i < lines.length; i++ )
|
||||||
error += lines[i] + "<br>";
|
error += lines[i] + "<br>";
|
||||||
}
|
}
|
||||||
sendCmd("QUIT", false );
|
sendCmd("QUIT", false);
|
||||||
if( socket != null ) {
|
if( socket != null ) {
|
||||||
try {
|
try {
|
||||||
socket.close();
|
socket.close();
|
||||||
}
|
} catch (IOException e1) {}
|
||||||
catch (IOException e1) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return mailSent;
|
return mailSent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A command to send and a result code to expect
|
||||||
|
* @since 0.9.13
|
||||||
|
*/
|
||||||
|
private static class SendExpect {
|
||||||
|
public final String send;
|
||||||
|
public final int expect;
|
||||||
|
|
||||||
|
public SendExpect(String s, int e) {
|
||||||
|
send = s;
|
||||||
|
expect = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A result string and code
|
||||||
|
* @since 0.9.13
|
||||||
|
*/
|
||||||
|
private static class Result {
|
||||||
|
public final int result;
|
||||||
|
public final String recv;
|
||||||
|
|
||||||
|
public Result(int r, String t) {
|
||||||
|
result = r;
|
||||||
|
recv = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** translate */
|
||||||
|
private static String _(String s) {
|
||||||
|
return Messages.getString(s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user