1   package com.atlassian.mail;
2   
3   import org.apache.commons.lang.StringUtils;
4   
5   import javax.mail.Multipart;
6   import java.util.HashMap;
7   import java.util.Map;
8   
9   public class Email
10  {
11      // mandatory fields
12      private String to;
13      private String subject;
14  
15      // optional fields
16      private String from;
17      private String fromName;
18      private String cc;
19      private String bcc;
20      private String replyTo;
21      private String inReplyTo;
22      private String body;
23      private String mimeType;
24      private String encoding;
25      private Multipart multipart;
26      private String messageId;
27      private Map headers;
28  
29      private void init(String to)
30      {
31          this.to = to;
32  
33          // set defaults
34          this.subject = "";
35          this.body = ""; // needs to be instantiated to empty string else send() will throw a NullPointer
36          this.mimeType = "text/plain";
37          this.encoding = "UTF-8";
38          this.headers = new HashMap();
39          loadDefaultHeaders();
40      }
41  
42      /**
43       * <b>Note</b>: By default the message has the "Precedence" header set to "bulk". Use {@link #removeHeader(java.lang.String)}
44       * to remove
45       *
46       * @param to
47       */
48      public Email(String to)
49      {
50          if (StringUtils.isBlank(to))
51              throw new IllegalArgumentException("'To' is a required field");
52  
53          init(to);
54      }
55  
56      /**
57       * <b>Note</b>: By default the message has the "Precedence" header set to "bulk". Use {@link #removeHeader(java.lang.String)}
58       * to remove
59       *
60       * @param to
61       */
62      public Email(String to, String cc, String bcc)
63      {
64          if (StringUtils.isBlank(to) && StringUtils.isBlank(cc) && StringUtils.isBlank(bcc))
65              throw new IllegalArgumentException("One of 'To', 'CC' or 'BCC' is required");
66  
67          init(to);
68          this.cc = cc;
69          this.bcc = bcc;
70      }
71  
72      protected void loadDefaultHeaders()
73      {
74          // Set the "Precedence" header to "bulk". All the mails coming from atlassian products likely need this header.
75          // This header should stop mail clients generating automatic messages to "answer" mail from atlassian products.
76          // For example, "away on holiday" messages. JRA-2622
77          headers.put("Precedence", "bulk");
78          headers.put("Auto-Submitted", "auto-generated"); // see JRA-15325
79      }
80  
81      public Email setFrom(String from)
82      {
83          this.from = from;
84          return this;
85      }
86  
87      public Email setFromName(String fromName)
88      {
89          this.fromName = fromName;
90          return this;
91      }
92  
93      public Email setTo(String to)
94      {
95          this.to = to;
96          return this;
97      }
98  
99      public Email setSubject(String subject)
100     {
101         this.subject = subject;
102         return this;
103     }
104 
105     public Email setCc(String cc)
106     {
107         this.cc = cc;
108         return this;
109     }
110 
111     public Email setBcc(String bcc)
112     {
113         this.bcc = bcc;
114         return this;
115     }
116 
117     public Email setReplyTo(String replyTo)
118     {
119         this.replyTo = replyTo;
120         return this;
121     }
122 
123     public Email setInReplyTo(String inReplyTo)
124     {
125         this.inReplyTo = inReplyTo;
126         return this;
127     }
128 
129     public Email setBody(String body)
130     {
131         this.body = body;
132         return this;
133     }
134 
135     public Email setMimeType(String mimeType)
136     {
137         this.mimeType = mimeType;
138         return this;
139     }
140 
141     public Email setEncoding(String encoding)
142     {
143         this.encoding = encoding;
144         return this;
145     }
146 
147     public Email setMultipart(Multipart multipart)
148     {
149         this.multipart = multipart;
150         return this;
151     }
152 
153     public String getFrom()
154     {
155         return from;
156     }
157 
158     public String getFromName()
159     {
160         return fromName;
161     }
162 
163     public String getTo()
164     {
165         return to;
166     }
167 
168     public String getSubject()
169     {
170         return subject;
171     }
172 
173     public String getCc()
174     {
175         return cc;
176     }
177 
178     public String getBcc()
179     {
180         return bcc;
181     }
182 
183     public String getReplyTo()
184     {
185         return replyTo;
186     }
187 
188     public String getInReplyTo()
189     {
190         return inReplyTo;
191     }
192 
193     public String getBody()
194     {
195         return body;
196     }
197 
198     public String getMimeType()
199     {
200         return mimeType;
201     }
202 
203     public String getEncoding()
204     {
205         return encoding;
206     }
207 
208     public Multipart getMultipart()
209     {
210         return multipart;
211     }
212 
213     public String getMessageId()
214     {
215         return messageId;
216     }
217 
218     public void setMessageId(String messageId)
219     {
220         this.messageId = messageId;
221     }
222 
223     /**
224      * Body is NOT included in comparing two Email objects
225      *
226      * @param o
227      * @return
228      */
229     public boolean equals(Object o)
230     {
231         if (this == o) return true;
232         if (!(o instanceof Email)) return false;
233 
234         final Email email = (Email) o;
235 
236         if (bcc != null ? !bcc.equals(email.bcc) : email.bcc != null) return false;
237         if (cc != null ? !cc.equals(email.cc) : email.cc != null) return false;
238         if (encoding != null ? !encoding.equals(email.encoding) : email.encoding != null) return false;
239         if (from != null ? !from.equals(email.from) : email.from != null) return false;
240         if (fromName != null ? !fromName.equals(email.fromName) : email.fromName != null) return false;
241         if (inReplyTo != null ? !inReplyTo.equals(email.inReplyTo) : email.inReplyTo != null) return false;
242         if (messageId != null ? !messageId.equals(email.messageId) : email.messageId != null) return false;
243         if (mimeType != null ? !mimeType.equals(email.mimeType) : email.mimeType != null) return false;
244         if (multipart != null ? !multipart.equals(email.multipart) : email.multipart != null) return false;
245         if (replyTo != null ? !replyTo.equals(email.replyTo) : email.replyTo != null) return false;
246         if (subject != null ? !subject.equals(email.subject) : email.subject != null) return false;
247         if (!to.equals(email.to)) return false;
248 
249         return true;
250     }
251 
252     /**
253      * Body is NOT included in calculating the hashCode for the object.
254      *
255      * @return
256      */
257     public int hashCode()
258     {
259         int result;
260         result = to.hashCode();
261         result = 29 * result + (subject != null ? subject.hashCode() : 0);
262         result = 29 * result + (from != null ? from.hashCode() : 0);
263         result = 29 * result + (fromName != null ? fromName.hashCode() : 0);
264         result = 29 * result + (cc != null ? cc.hashCode() : 0);
265         result = 29 * result + (bcc != null ? bcc.hashCode() : 0);
266         result = 29 * result + (replyTo != null ? replyTo.hashCode() : 0);
267         result = 29 * result + (inReplyTo != null ? inReplyTo.hashCode() : 0);
268         result = 29 * result + (mimeType != null ? mimeType.hashCode() : 0);
269         result = 29 * result + (encoding != null ? encoding.hashCode() : 0);
270         result = 29 * result + (multipart != null ? multipart.hashCode() : 0);
271         result = 29 * result + (messageId != null ? messageId.hashCode() : 0);
272         return result;
273     }
274 
275     public String toString()
276     {
277         return "To='" + to + "' Subject='" + subject + "' From='" + from + "' FromName='" + fromName + "' Cc='" + cc +
278                 "' Bcc='" + bcc + "' ReplyTo='" + replyTo + "' InReplyTo='" + inReplyTo + "' MimeType='" + mimeType +
279                 "' Encoding='" + encoding + "' Multipart='" + multipart + "' MessageId='" + messageId + "'";
280     }
281 
282     public void addHeader(String headerName, String headerValue)
283     {
284         headers.put(headerName, headerValue);
285     }
286 
287     /**
288      * @param headerName
289      * @return the value of the removed header
290      */
291     public String removeHeader(String headerName)
292     {
293         if (headers.containsKey(headerName))
294         {
295             return (String) headers.remove(headerName);
296         }
297         else
298         {
299             return null;
300         }
301     }
302 
303     public Map getHeaders()
304     {
305         return headers;
306     }
307 }