import org.cacert.gigi.crypto.SMIME;
import org.cacert.gigi.database.GigiPreparedStatement;
import org.cacert.gigi.util.DNSUtil;
+import org.cacert.gigi.util.DomainAssessment;
public abstract class EmailProvider {
- public abstract void sendmail(String to, String subject, String message, String from, String replyto, String toname, String fromname, String errorsto, boolean extra) throws IOException;
+ public abstract void sendMail(String to, String subject, String message, String replyto, String toname, String fromname, String errorsto, boolean extra) throws IOException;
private static EmailProvider instance;
}
protected final void sendSigned(String contents, PrintWriter output) throws IOException, GeneralSecurityException {
- SMIME.smime(contents, k, c, output);
+ if (k == null || c == null) {
+ output.println("Content-Transfer-Encoding: base64");
+ output.println();
+ output.print(contents);
+ } else {
+ SMIME.smime(contents, k, c, output);
+ }
}
public static EmailProvider getInstance() {
public static final String FAIL = "FAIL";
- public static final Pattern MAIL = Pattern.compile("^([a-zA-Z0-9])+([a-zA-Z0-9\\+\\._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9\\._-]+)+$");
+ private static final String MAIL_P_RFC_WORD = "[A-Za-z0-9\\+\\.!#$%&'*/=?^_`|~{}-]+";
+
+ private static final String MAIL_P_RFC_LOCAL = MAIL_P_RFC_WORD + "(?:\\." + MAIL_P_RFC_WORD + ")*";
+
+ private static final String MAIL_P_RFC_LABEL = "(?!(?!xn)..--|-)(?:[A-Za-z0-9-]+)(?<!-)";
+
+ private static final String MAIL_P_RFC_ADDRESS = MAIL_P_RFC_LOCAL + "@(?:" + MAIL_P_RFC_LABEL + "\\.)+" + MAIL_P_RFC_LABEL + "\\.?";
+
+ private static final Pattern MAIL_LOCAL = Pattern.compile("^" + MAIL_P_RFC_LOCAL + "$");
+
+ private static final Pattern MAIL_ADDRESS = Pattern.compile("^" + MAIL_P_RFC_ADDRESS + "$");
public String checkEmailServer(int forUid, String address) throws IOException {
- if (MAIL.matcher(address).matches()) {
+ if (isValidMailAddress(address)) {
String[] parts = address.split("@", 2);
String domain = parts[1];
} else {
return "Strange MX records.";
}
- try (Socket s = new Socket(host, 25); BufferedReader br0 = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8"));//
+ try (Socket s = new Socket(host, 25);
+ BufferedReader br0 = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8"));//
PrintWriter pw0 = new PrintWriter(new OutputStreamWriter(s.getOutputStream(), "UTF-8"))) {
BufferedReader br = br0;
PrintWriter pw = pw0;
String line;
- if ( !Sendmail.readSMTPResponse(br, 220)) {
+ if ( !SendMail.readSMTPResponse(br, 220)) {
continue;
}
if (starttls) {
pw.print("STARTTLS\r\n");
pw.flush();
- if ( !Sendmail.readSMTPResponse(br, 220)) {
+ if ( !SendMail.readSMTPResponse(br, 220)) {
continue;
}
Socket s1 = ((SSLSocketFactory) SSLSocketFactory.getDefault()).createSocket(s, host, 25, true);
pw = new PrintWriter(new OutputStreamWriter(s1.getOutputStream(), "UTF-8"));
pw.print("EHLO www.cacert.org\r\n");
pw.flush();
- if ( !Sendmail.readSMTPResponse(br, 250)) {
+ if ( !SendMail.readSMTPResponse(br, 250)) {
continue;
}
}
pw.print("MAIL FROM: <returns@cacert.org>\r\n");
pw.flush();
- if ( !Sendmail.readSMTPResponse(br, 250)) {
+ if ( !SendMail.readSMTPResponse(br, 250)) {
continue;
}
pw.print("RCPT TO: <" + address + ">\r\n");
pw.flush();
- if ( !Sendmail.readSMTPResponse(br, 250)) {
+ if ( !SendMail.readSMTPResponse(br, 250)) {
continue;
}
pw.print("QUIT\r\n");
pw.flush();
- if ( !Sendmail.readSMTPResponse(br, 221)) {
+ if ( !SendMail.readSMTPResponse(br, 221)) {
continue;
}
});
}
+ public static boolean isValidMailAddress(String address) {
+ if ( !MAIL_ADDRESS.matcher(address).matches()) {
+ return false;
+ }
+
+ String[] parts = address.split("@", 2);
+
+ String local = parts[0];
+ String domain = parts[1];
+
+ if ( !MAIL_LOCAL.matcher(local).matches()) {
+ return false;
+ }
+
+ for (String domainPart : domain.split("\\.", -1)) {
+ if ( !DomainAssessment.isValidDomainPart(domainPart)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
}