1
2
3
4
5
6
7
8
9
10
11 package com.atlassian.mail.server.impl;
12
13 import alt.javax.mail.Session;
14 import alt.javax.mail.SessionImpl;
15 import alt.javax.mail.internet.MimeMessage;
16 import alt.javax.mail.internet.MimeMessageImpl;
17 import com.atlassian.mail.Email;
18 import com.atlassian.mail.MailException;
19 import com.atlassian.mail.MailFactory;
20 import com.atlassian.mail.config.PropertiesLoader;
21 import com.atlassian.mail.server.AbstractMailServer;
22 import com.atlassian.mail.server.MailServerManager;
23 import com.atlassian.mail.server.SMTPMailServer;
24 import com.atlassian.mail.server.impl.util.MessageCreator;
25 import com.opensymphony.util.TextUtils;
26 import org.apache.commons.lang.builder.ToStringBuilder;
27 import org.apache.log4j.Category;
28
29 import javax.mail.Authenticator;
30 import javax.mail.MessagingException;
31 import javax.mail.PasswordAuthentication;
32 import javax.naming.Context;
33 import javax.naming.InitialContext;
34 import javax.naming.NamingException;
35 import java.io.PrintStream;
36 import java.io.UnsupportedEncodingException;
37 import java.util.Properties;
38
39 public class SMTPMailServerImpl extends AbstractMailServer implements SMTPMailServer
40 {
41 private static final Category log = Category.getInstance(SMTPMailServerImpl.class);
42
43 private boolean isSessionServer;
44 private String defaultFrom;
45 private String prefix;
46 private String jndiLocation;
47 private String smtpPort = DEFAULT_SMTP_PORT;
48 private boolean removePrecedence;
49 private boolean debug;
50
51 private transient PrintStream debugStream;
52 private transient Session session;
53
54 public SMTPMailServerImpl()
55 {
56 }
57
58 public SMTPMailServerImpl(Long id, String name, String description, String from, String prefix, boolean isSession, String location, String username, String password)
59 {
60 this(id, name, description, from, prefix, isSession, location, username, password, SMTPMailServer.DEFAULT_SMTP_PORT);
61 }
62
63 public SMTPMailServerImpl(Long id, String name, String description, String from, String prefix, boolean isSession, String location, String username, String password, String smtpPort)
64 {
65 this(id, name, description, from, prefix, isSession, false, location, username, password, smtpPort);
66 }
67
68 public SMTPMailServerImpl(Long id, String name, String description, String from, String prefix, boolean isSession, boolean removePrecedence, String location, String username, String password, String smtpPort)
69 {
70 super(id, name, description, location, username, password);
71 setDefaultFrom(from);
72 setPrefix(prefix);
73 setSessionServer(isSession);
74 setSmtpPort(smtpPort);
75 setRemovePrecedence(removePrecedence);
76
77 if (isSession)
78 {
79 setJndiLocation(location);
80 setHostname(null);
81 }
82 }
83
84 public String getJndiLocation()
85 {
86 return jndiLocation;
87 }
88
89 public void setJndiLocation(String jndiLocation)
90 {
91 this.jndiLocation = jndiLocation;
92 propertyChanged();
93 }
94
95 protected Authenticator getAuthenticator()
96 {
97 return new MyAuthenticator();
98 }
99
100
101
102
103 public Session getSession() throws NamingException, MailException
104 {
105 if (session == null)
106
107 {
108 if (isSessionServer())
109 {
110 Object jndiSession = getJndiSession();
111 if (jndiSession instanceof javax.mail.Session)
112 {
113 session = new SessionImpl((javax.mail.Session) jndiSession);
114 }
115 else
116 {
117 log.error("Mail server at location [" + getJndiLocation() + "] is not of required type javax.mail.Session, or is in different classloader. " +
118 "It is of type '" + (jndiSession != null ? jndiSession.getClass().getName() : null) + "' in classloader '"+jndiSession.getClass().getClassLoader()+"' instead");
119 throw new IllegalArgumentException("Mail server at location [" + getJndiLocation() + "] is not of required type javax.mail.Session. ");
120 }
121 }
122 else
123 {
124 Properties props = new Properties();
125 props.put("mail.smtp.host", getHostname());
126 props.put("mail.smtp.port", getSmtpPort());
127 props.put("mail.transport.protocol", "smtp");
128 props.put("mail.debug", ""+debug);
129
130 if (Boolean.getBoolean("mail.debug"))
131 {
132 props.put("mail.debug", "true");
133 }
134 Authenticator auth = null;
135 if (TextUtils.stringSet(getUsername()))
136 {
137 props.put("mail.smtp.auth", "true");
138 auth = getAuthenticator();
139 }
140 props.putAll(PropertiesLoader.ATLASSIAN_MAIL_PROPERTIES);
141 session = MailFactory.getServerManager().getSession(props, auth);
142 if (debugStream != null)
143 {
144 try
145 {
146 session.getWrappedSession().setDebugOut(debugStream);
147 } catch (NoSuchMethodError nsme)
148 {
149
150 log.error("Warning: An old (pre-1.3.2) version of the JavaMail library (javamail.jar or mail.jar) bundled with your app server, is in use. Some functions such as IMAPS/POPS/SMTPS will not work. Consider upgrading the app server's javamail jar to the version JIRA provides.");
151 }
152 }
153 }
154 }
155 return session;
156 }
157
158 protected Object getJndiSession() throws NamingException
159 {
160 Context ctx = new InitialContext();
161 Object jndiSession = ctx.lookup(getJndiLocation());
162 return jndiSession;
163 }
164
165 public void send(Email email) throws MailException
166 {
167 try
168 {
169 Session thisSession = getSession();
170
171 MimeMessage message = new MimeMessageImpl(thisSession);
172 MessageCreator messageCreator = new MessageCreator();
173
174 messageCreator.updateMimeMessage(email, getDefaultFrom(), prefix, message);
175
176
177 thisSession.getTransport("smtp").send(message);
178
179
180 if (message.getHeader("Message-Id") != null && message.getHeader("Message-Id").length > 0)
181 {
182 email.setMessageId(message.getHeader("Message-Id")[0]);
183 }
184 }
185 catch (NamingException e)
186 {
187 throw new MailException(e);
188 }
189 catch (MessagingException e)
190 {
191 throw new MailException(e);
192 }
193 catch (UnsupportedEncodingException e)
194 {
195 log.debug("Error setting the 'from' address with an email and the user's fullname");
196 e.printStackTrace();
197 }
198 }
199
200
201
202
203
204 public void quietSend(Email email) throws MailException
205 {
206 try
207 {
208 send(email);
209 }
210 catch (Exception e)
211 {
212 log.error("Error sending mail. to:" + email.getTo() + ", cc:" + email.getCc() + ", bcc:" + email.getBcc() + ", subject:" + email.getSubject() + ", body:" + email.getBody() + ", mimeType:" + email.getMimeType() + ", encoding:" + email.getEncoding() + ", multipart:" + email.getMultipart() + ", error:" + e, e);
213 }
214 }
215
216 public String getType()
217 {
218 return MailServerManager.SERVER_TYPES[1];
219 }
220
221 public String getDefaultFrom()
222 {
223 return defaultFrom;
224 }
225
226 public void setDefaultFrom(String defaultFrom)
227 {
228 this.defaultFrom = defaultFrom;
229 propertyChanged();
230 }
231
232 public String getPrefix()
233 {
234 return prefix;
235 }
236
237 public void setPrefix(String prefix)
238 {
239 this.prefix = prefix;
240 }
241
242 public boolean isRemovePrecedence()
243 {
244 return removePrecedence;
245 }
246
247 public void setRemovePrecedence(boolean precedence)
248 {
249 this.removePrecedence = precedence;
250 propertyChanged();
251 }
252
253 public String getSmtpPort()
254 {
255 return smtpPort;
256 }
257
258 public void setSmtpPort(String smtpPort)
259 {
260 this.smtpPort = smtpPort;
261 propertyChanged();
262 }
263
264 public void setDebug(boolean debug) {
265 this.debug = debug;
266 propertyChanged();
267 }
268
269 public void setDebugStream(PrintStream debugStream) {
270 this.debugStream = debugStream;
271 propertyChanged();
272 }
273
274
275 public boolean getDebug() {
276 return this.debug;
277 }
278
279 public PrintStream getDebugStream() {
280 return this.debugStream;
281 }
282
283 public boolean isSessionServer()
284 {
285 return isSessionServer;
286 }
287
288 public void setSessionServer(boolean sessionServer)
289 {
290 isSessionServer = sessionServer;
291 propertyChanged();
292 }
293
294 private class MyAuthenticator extends Authenticator
295 {
296 public PasswordAuthentication getPasswordAuthentication()
297 {
298 return new PasswordAuthentication(getUsername(), getPassword());
299 }
300 }
301
302
303 public boolean equals(Object o)
304 {
305 if (this == o)
306 {
307 return true;
308 }
309 if (!(o instanceof SMTPMailServerImpl))
310 {
311 return false;
312 }
313 if (!super.equals(o))
314 {
315 return false;
316 }
317
318 final SMTPMailServerImpl smtpMailServer = (SMTPMailServerImpl) o;
319
320 if (isSessionServer != smtpMailServer.isSessionServer)
321 {
322 return false;
323 }
324 if (defaultFrom != null ? !defaultFrom.equals(smtpMailServer.defaultFrom) : smtpMailServer.defaultFrom != null)
325 {
326 return false;
327 }
328 if (prefix != null ? !prefix.equals(smtpMailServer.prefix) : smtpMailServer.prefix != null)
329 {
330 return false;
331 }
332 if (smtpPort != null ? !smtpPort.equals(smtpMailServer.smtpPort) : smtpMailServer.smtpPort != null)
333 {
334 return false;
335 }
336 if (removePrecedence != smtpMailServer.removePrecedence)
337 {
338 return false;
339 }
340
341 return true;
342 }
343
344 public int hashCode()
345 {
346 int result = super.hashCode();
347 result = 29 * result + (isSessionServer ? 1 : 0);
348 result = 29 * result + (defaultFrom != null ? defaultFrom.hashCode() : 0);
349 result = 29 * result + (prefix != null ? prefix.hashCode() : 0);
350 result = 29 * result + (smtpPort != null ? smtpPort.hashCode() : 0);
351 result = 29 * result + (removePrecedence ? 1 : 0);
352 return result;
353 }
354
355 public String toString()
356 {
357 return new ToStringBuilder(this).append("id", getId()).append("name", getName()).append("description", getDescription()).append("server name", getHostname()).append("username", getUsername()).append("password", getPassword()).append("isSessionServer", isSessionServer).append("defaultFrom", defaultFrom).append("prefix", prefix).append("smtpPort", smtpPort).toString();
358 }
359
360
361
362
363 protected void propertyChanged()
364 {
365 super.propertyChanged();
366 session = null;
367 }
368 }