]> WPIA git - gigi.git/blob - src/org/cacert/gigi/email/EmailProvider.java
Merge remote-tracking branch 'origin/emailMgmt'
[gigi.git] / src / org / cacert / gigi / email / EmailProvider.java
1 package org.cacert.gigi.email;
2
3 import java.io.BufferedReader;
4 import java.io.IOException;
5 import java.io.InputStreamReader;
6 import java.io.PrintWriter;
7 import java.net.Socket;
8 import java.sql.PreparedStatement;
9 import java.sql.SQLException;
10 import java.util.LinkedList;
11 import java.util.Properties;
12 import java.util.regex.Pattern;
13
14 import org.cacert.gigi.database.DatabaseConnection;
15
16 public abstract class EmailProvider {
17         public abstract void sendmail(String to, String subject, String message, String from, String replyto,
18                 String toname, String fromname, String errorsto, boolean extra) throws IOException;
19
20         private static EmailProvider instance;
21
22         public static EmailProvider getInstance() {
23                 return instance;
24         }
25
26         protected static void setInstance(EmailProvider instance) {
27                 EmailProvider.instance = instance;
28         }
29
30         public static void init(Properties conf) {
31                 try {
32                         Class<?> c = Class.forName(conf.getProperty("emailProvider"));
33                         instance = (EmailProvider) c.getDeclaredConstructor(Properties.class).newInstance(conf);
34                 } catch (ReflectiveOperationException e) {
35                         e.printStackTrace();
36                 }
37         }
38
39         public static final String OK = "OK";
40         public static final String FAIL = "FAIL";
41         public static final Pattern MAIL = Pattern
42                 .compile("^([a-zA-Z0-9])+([a-zA-Z0-9\\+\\._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9\\._-]+)+$");
43
44         public String checkEmailServer(int forUid, String address) throws IOException {
45                 if (MAIL.matcher(address).matches()) {
46                         String[] parts = address.split("@", 2);
47                         String domain = parts[1];
48
49                         LinkedList<String> mxhosts = getMxHosts(domain);
50
51                         for (String host : mxhosts) {
52                                 try (Socket s = new Socket(host, 25);
53                                         BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
54                                         PrintWriter pw = new PrintWriter(s.getOutputStream())) {
55                                         String line;
56                                         while ((line = br.readLine()) != null && line.startsWith("220-")) {
57                                         }
58                                         if (line == null || !line.startsWith("220")) {
59                                                 continue;
60                                         }
61
62                                         pw.print("HELO www.cacert.org\r\n");
63                                         pw.flush();
64
65                                         while ((line = br.readLine()) != null && line.startsWith("220")) {
66                                         }
67
68                                         if (line == null || !line.startsWith("250")) {
69                                                 continue;
70                                         }
71                                         pw.print("MAIL FROM: <returns@cacert.org>\r\n");
72                                         pw.flush();
73
74                                         line = br.readLine();
75
76                                         if (line == null || !line.startsWith("250")) {
77                                                 continue;
78                                         }
79                                         pw.print("RCPT TO: <" + address + ">\r\n");
80                                         pw.flush();
81
82                                         line = br.readLine();
83                                         pw.print("QUIT\r\n");
84                                         pw.flush();
85
86                                         try {
87                                                 PreparedStatement statmt = DatabaseConnection.getInstance().prepare(
88                                                         "insert into `pinglog` set `when`=NOW(), `email`=?, `result`=?, `uid`=?");
89                                                 statmt.setString(1, address);
90                                                 statmt.setString(2, line);
91                                                 statmt.setInt(3, forUid);
92                                                 statmt.execute();
93                                         } catch (SQLException e) {
94                                                 e.printStackTrace();
95                                         }
96
97                                         if (line == null || !line.startsWith("250")) {
98                                                 return line;
99                                         } else {
100                                                 return OK;
101                                         }
102                                 }
103
104                         }
105                 }
106                 try {
107                         PreparedStatement statmt = DatabaseConnection.getInstance().prepare(
108                                 "insert into `pinglog` set `when`=NOW(), `email`=?, `result`=?, `uid`=?");
109                         statmt.setString(1, address);
110                         statmt.setString(2, "Failed to make a connection to the mail server");
111                         statmt.setInt(3, forUid);
112                         statmt.execute();
113                 } catch (SQLException e) {
114                         e.printStackTrace();
115                 }
116                 return FAIL;
117         }
118
119         private static LinkedList<String> getMxHosts(String domain) throws IOException {
120                 LinkedList<String> mxhosts = new LinkedList<String>();
121                 Process dig = Runtime.getRuntime().exec(new String[] { "dig", "+short", "MX", domain });
122                 try (BufferedReader br = new BufferedReader(new InputStreamReader(dig.getInputStream()))) {
123                         String line;
124                         while ((line = br.readLine()) != null) {
125                                 String[] mxparts = line.split(" ", 2);
126                                 if (mxparts.length != 2) {
127                                         continue;
128                                 }
129                                 mxhosts.add(mxparts[1].substring(0, mxparts[1].length() - 1));
130                         }
131                 }
132                 return mxhosts;
133         }
134 }