1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.mail;
18
19 import java.io.UnsupportedEncodingException;
20 import java.nio.charset.Charset;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Date;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Properties;
29
30 import javax.mail.Authenticator;
31 import javax.mail.Message;
32 import javax.mail.MessagingException;
33 import javax.mail.Session;
34 import javax.mail.Store;
35 import javax.mail.Transport;
36 import javax.mail.internet.AddressException;
37 import javax.mail.internet.InternetAddress;
38 import javax.mail.internet.MimeMessage;
39 import javax.mail.internet.MimeMultipart;
40 import javax.naming.Context;
41 import javax.naming.InitialContext;
42 import javax.naming.NamingException;
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 public abstract class Email
64 {
65
66
67
68 public static final String SENDER_EMAIL = "sender.email";
69
70 public static final String SENDER_NAME = "sender.name";
71
72 public static final String RECEIVER_EMAIL = "receiver.email";
73
74 public static final String RECEIVER_NAME = "receiver.name";
75
76 public static final String EMAIL_SUBJECT = "email.subject";
77
78 public static final String EMAIL_BODY = "email.body";
79
80 public static final String CONTENT_TYPE = "content.type";
81
82
83 public static final String MAIL_HOST = "mail.smtp.host";
84
85 public static final String MAIL_PORT = "mail.smtp.port";
86
87 public static final String MAIL_SMTP_FROM = "mail.smtp.from";
88
89 public static final String MAIL_SMTP_AUTH = "mail.smtp.auth";
90
91 public static final String MAIL_SMTP_USER = "mail.smtp.user";
92
93 public static final String MAIL_SMTP_PASSWORD = "mail.smtp.password";
94
95 public static final String MAIL_TRANSPORT_PROTOCOL =
96 "mail.transport.protocol";
97
98
99
100 public static final String MAIL_TRANSPORT_TLS = "mail.smtp.starttls.enable";
101
102 public static final String MAIL_SMTP_SOCKET_FACTORY_FALLBACK = "mail.smtp.socketFactory.fallback";
103
104 public static final String MAIL_SMTP_SOCKET_FACTORY_CLASS = "mail.smtp.socketFactory.class";
105
106 public static final String MAIL_SMTP_SOCKET_FACTORY_PORT = "mail.smtp.socketFactory.port";
107
108 public static final String SMTP = "smtp";
109
110 public static final String TEXT_HTML = "text/html";
111
112 public static final String TEXT_PLAIN = "text/plain";
113
114 public static final String ATTACHMENTS = "attachments";
115
116 public static final String FILE_SERVER = "file.server";
117
118 public static final String MAIL_DEBUG = "mail.debug";
119
120
121 public static final String KOI8_R = "koi8-r";
122
123 public static final String ISO_8859_1 = "iso-8859-1";
124
125 public static final String US_ASCII = "us-ascii";
126
127
128 protected MimeMessage message;
129
130
131 protected String charset;
132
133
134 protected InternetAddress fromAddress;
135
136
137 protected String subject;
138
139
140 protected MimeMultipart emailBody;
141
142
143 protected Object content;
144
145
146 protected String contentType;
147
148
149 protected boolean debug;
150
151
152 protected Date sentDate;
153
154
155
156
157
158 protected Authenticator authenticator;
159
160
161
162
163
164 protected String hostName;
165
166
167
168
169
170 protected String smtpPort = "25";
171
172
173
174
175
176 protected String sslSmtpPort = "465";
177
178
179 protected List toList = new ArrayList();
180
181
182 protected List ccList = new ArrayList();
183
184
185 protected List bccList = new ArrayList();
186
187
188 protected List replyList = new ArrayList();
189
190
191
192
193
194
195
196 protected String bounceAddress;
197
198
199
200
201
202
203
204
205 protected Map headers = new HashMap();
206
207
208
209
210 protected boolean popBeforeSmtp;
211
212 protected String popHost;
213
214 protected String popUsername;
215
216 protected String popPassword;
217
218
219 protected boolean tls;
220
221 protected boolean ssl;
222
223
224 private Session session;
225
226
227
228
229
230
231
232 public void setDebug(boolean d)
233 {
234 this.debug = d;
235 }
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250 public void setAuthentication(String userName, String password)
251 {
252 this.authenticator = new DefaultAuthenticator(userName, password);
253 this.setAuthenticator(this.authenticator);
254 }
255
256
257
258
259
260
261
262
263
264
265
266
267 public void setAuthenticator(Authenticator newAuthenticator)
268 {
269 this.authenticator = newAuthenticator;
270 }
271
272
273
274
275
276
277
278
279
280
281 public void setCharset(String newCharset)
282 {
283 Charset set = Charset.forName(newCharset);
284 this.charset = set.name();
285 }
286
287
288
289
290
291
292
293 public void setContent(MimeMultipart aMimeMultipart)
294 {
295 this.emailBody = aMimeMultipart;
296 }
297
298
299
300
301
302
303
304
305 public void setContent(Object aObject, String aContentType)
306 {
307 this.content = aObject;
308 if (EmailUtils.isEmpty(aContentType))
309 {
310 this.contentType = null;
311 }
312 else
313 {
314
315 this.contentType = aContentType;
316
317
318 String strMarker = "; charset=";
319 int charsetPos = aContentType.toLowerCase().indexOf(strMarker);
320
321 if (charsetPos != -1)
322 {
323
324 charsetPos += strMarker.length();
325 int intCharsetEnd =
326 aContentType.toLowerCase().indexOf(" ", charsetPos);
327
328 if (intCharsetEnd != -1)
329 {
330 this.charset =
331 aContentType.substring(charsetPos, intCharsetEnd);
332 }
333 else
334 {
335 this.charset = aContentType.substring(charsetPos);
336 }
337 }
338 else
339 {
340
341
342 if (this.contentType.startsWith("text/") && EmailUtils.isNotEmpty(this.charset))
343 {
344 StringBuffer contentTypeBuf = new StringBuffer(this.contentType);
345 contentTypeBuf.append(strMarker);
346 contentTypeBuf.append(this.charset);
347 this.contentType = contentTypeBuf.toString();
348 }
349 }
350 }
351 }
352
353
354
355
356
357
358
359 public void setHostName(String aHostName)
360 {
361 this.hostName = aHostName;
362 }
363
364
365
366
367
368
369
370 public void setTLS(boolean withTLS)
371 {
372 this.tls = withTLS;
373 }
374
375
376
377
378
379
380 public void setSmtpPort(int aPortNumber)
381 {
382 if (aPortNumber < 1)
383 {
384 throw new IllegalArgumentException(
385 "Cannot connect to a port number that is less than 1 ( "
386 + aPortNumber
387 + " )");
388 }
389
390 this.smtpPort = Integer.toString(aPortNumber);
391 }
392
393
394
395
396
397
398 public void setMailSession(Session aSession)
399 {
400 Properties sessionProperties = aSession.getProperties();
401 String auth = sessionProperties.getProperty(MAIL_SMTP_AUTH);
402 if ("true".equalsIgnoreCase(auth))
403 {
404 String userName = sessionProperties.getProperty(MAIL_SMTP_USER);
405 String password = sessionProperties.getProperty(MAIL_SMTP_PASSWORD);
406 this.authenticator = new DefaultAuthenticator(userName, password);
407 this.session = Session.getInstance(sessionProperties, this.authenticator);
408 }
409 else
410 {
411 this.session = aSession;
412 }
413 }
414
415
416
417
418
419
420
421
422
423 public void setMailSessionFromJNDI(String jndiName) throws NamingException
424 {
425 if (EmailUtils.isEmpty(jndiName))
426 {
427 throw new IllegalArgumentException("JNDI name missing");
428 }
429 Context ctx = null;
430 if (jndiName.startsWith("java:"))
431 {
432 ctx = new InitialContext();
433 }
434 else
435 {
436 ctx = (Context) new InitialContext().lookup("java:comp/env");
437
438 }
439 this.setMailSession((Session) ctx.lookup(jndiName));
440 }
441
442
443
444
445
446
447
448
449 public Session getMailSession() throws EmailException
450 {
451 if (this.session == null)
452 {
453 Properties properties = new Properties(System.getProperties());
454 properties.setProperty(MAIL_TRANSPORT_PROTOCOL, SMTP);
455
456 if (EmailUtils.isEmpty(this.hostName))
457 {
458 this.hostName = properties.getProperty(MAIL_HOST);
459 }
460
461 if (EmailUtils.isEmpty(this.hostName))
462 {
463 throw new EmailException(
464 "Cannot find valid hostname for mail session");
465 }
466
467 properties.setProperty(MAIL_PORT, smtpPort);
468 properties.setProperty(MAIL_HOST, hostName);
469 properties.setProperty(MAIL_DEBUG, String.valueOf(this.debug));
470
471 if (this.authenticator != null)
472 {
473 properties.setProperty(MAIL_TRANSPORT_TLS, tls ? "true" : "false");
474 properties.setProperty(MAIL_SMTP_AUTH, "true");
475 }
476
477 if (this.ssl)
478 {
479 properties.setProperty(MAIL_PORT, sslSmtpPort);
480 properties.setProperty(MAIL_SMTP_SOCKET_FACTORY_PORT, sslSmtpPort);
481 properties.setProperty(MAIL_SMTP_SOCKET_FACTORY_CLASS, "javax.net.ssl.SSLSocketFactory");
482 properties.setProperty(MAIL_SMTP_SOCKET_FACTORY_FALLBACK, "false");
483 }
484
485 if (this.bounceAddress != null)
486 {
487 properties.setProperty(MAIL_SMTP_FROM, this.bounceAddress);
488 }
489
490
491
492 this.session =
493 Session.getInstance(properties, this.authenticator);
494 }
495 return this.session;
496 }
497
498
499
500
501
502
503
504
505
506
507 private InternetAddress createInternetAddress(String email, String name, String charsetName)
508 throws EmailException
509 {
510 InternetAddress address = null;
511
512 try
513 {
514 address = new InternetAddress(email);
515
516
517 if (EmailUtils.isEmpty(name))
518 {
519 name = email;
520 }
521
522
523 if (EmailUtils.isEmpty(charsetName))
524 {
525 address.setPersonal(name);
526 }
527 else
528 {
529
530
531 Charset set = Charset.forName(charsetName);
532 address.setPersonal(name, set.name());
533 }
534
535
536
537 address.validate();
538 }
539 catch (AddressException e)
540 {
541 throw new EmailException(e);
542 }
543 catch (UnsupportedEncodingException e)
544 {
545 throw new EmailException(e);
546 }
547 return address;
548 }
549
550
551
552
553
554
555
556
557
558
559
560
561
562 public Email setFrom(String email)
563 throws EmailException
564 {
565 return setFrom(email, null);
566 }
567
568
569
570
571
572
573
574
575
576
577
578
579
580 public Email setFrom(String email, String name)
581 throws EmailException
582 {
583 return setFrom(email, name, null);
584 }
585
586
587
588
589
590
591
592
593
594
595
596
597 public Email setFrom(String email, String name, String charset)
598 throws EmailException
599 {
600 this.fromAddress = createInternetAddress(email, name, charset);
601 return this;
602 }
603
604
605
606
607
608
609
610
611
612
613
614
615 public Email addTo(String email)
616 throws EmailException
617 {
618 return addTo(email, null);
619 }
620
621
622
623
624
625
626
627
628
629
630
631
632
633 public Email addTo(String email, String name)
634 throws EmailException
635 {
636 return addTo(email, name, null);
637 }
638
639
640
641
642
643
644
645
646
647
648
649
650 public Email addTo(String email, String name, String charset)
651 throws EmailException
652 {
653 this.toList.add(createInternetAddress(email, name, charset));
654 return this;
655 }
656
657
658
659
660
661
662
663
664
665
666
667
668 public Email setTo(Collection aCollection) throws EmailException
669 {
670 if (aCollection == null || aCollection.isEmpty())
671 {
672 throw new EmailException("Address List provided was invalid");
673 }
674
675 this.toList = new ArrayList(aCollection);
676 return this;
677 }
678
679
680
681
682
683
684
685
686
687
688
689
690 public Email addCc(String email)
691 throws EmailException
692 {
693 return this.addCc(email, null);
694 }
695
696
697
698
699
700
701
702
703
704
705
706
707
708 public Email addCc(String email, String name)
709 throws EmailException
710 {
711 return addCc(email, name, null);
712 }
713
714
715
716
717
718
719
720
721
722
723
724
725 public Email addCc(String email, String name, String charset)
726 throws EmailException
727 {
728 this.ccList.add(createInternetAddress(email, name, charset));
729 return this;
730 }
731
732
733
734
735
736
737
738
739
740
741
742
743 public Email setCc(Collection aCollection) throws EmailException
744 {
745 if (aCollection == null || aCollection.isEmpty())
746 {
747 throw new EmailException("Address List provided was invalid");
748 }
749
750 this.ccList = new ArrayList(aCollection);
751 return this;
752 }
753
754
755
756
757
758
759
760
761
762
763
764
765 public Email addBcc(String email)
766 throws EmailException
767 {
768 return this.addBcc(email, null);
769 }
770
771
772
773
774
775
776
777
778
779
780
781
782
783 public Email addBcc(String email, String name)
784 throws EmailException
785 {
786 return addBcc(email, name, null);
787 }
788
789
790
791
792
793
794
795
796
797
798
799
800 public Email addBcc(String email, String name, String charset)
801 throws EmailException
802 {
803 this.bccList.add(createInternetAddress(email, name, charset));
804 return this;
805 }
806
807
808
809
810
811
812
813
814
815
816
817
818 public Email setBcc(Collection aCollection) throws EmailException
819 {
820 if (aCollection == null || aCollection.isEmpty())
821 {
822 throw new EmailException("Address List provided was invalid");
823 }
824
825 this.bccList = new ArrayList(aCollection);
826 return this;
827 }
828
829
830
831
832
833
834
835
836
837
838
839
840 public Email addReplyTo(String email)
841 throws EmailException
842 {
843 return this.addReplyTo(email, null);
844 }
845
846
847
848
849
850
851
852
853
854
855
856
857
858 public Email addReplyTo(String email, String name)
859 throws EmailException
860 {
861 return addReplyTo(email, name, null);
862 }
863
864
865
866
867
868
869
870
871
872
873
874
875 public Email addReplyTo(String email, String name, String charset)
876 throws EmailException
877 {
878 this.replyList.add(createInternetAddress(email, name, charset));
879 return this;
880 }
881
882
883
884
885
886
887
888
889
890
891
892
893 public Email setReplyTo(Collection aCollection) throws EmailException
894 {
895 if (aCollection == null || aCollection.isEmpty())
896 {
897 throw new EmailException("Address List provided was invalid");
898 }
899
900 this.replyList = new ArrayList(aCollection);
901 return this;
902 }
903
904
905
906
907
908
909
910
911
912
913
914 public void setHeaders(Map map)
915 {
916 Iterator iterKeyBad = map.entrySet().iterator();
917
918 while (iterKeyBad.hasNext())
919 {
920 Map.Entry entry = (Map.Entry) iterKeyBad.next();
921 String strName = (String) entry.getKey();
922 String strValue = (String) entry.getValue();
923
924 if (EmailUtils.isEmpty(strName))
925 {
926 throw new IllegalArgumentException("name can not be null");
927 }
928 if (EmailUtils.isEmpty(strValue))
929 {
930 throw new IllegalArgumentException("value can not be null");
931 }
932 }
933
934
935 this.headers = map;
936 }
937
938
939
940
941
942
943
944
945 public void addHeader(String name, String value)
946 {
947 if (EmailUtils.isEmpty(name))
948 {
949 throw new IllegalArgumentException("name can not be null");
950 }
951 if (EmailUtils.isEmpty(value))
952 {
953 throw new IllegalArgumentException("value can not be null");
954 }
955
956 this.headers.put(name, value);
957 }
958
959
960
961
962
963
964
965
966 public Email setSubject(String aSubject)
967 {
968 this.subject = aSubject;
969 return this;
970 }
971
972
973
974
975
976
977
978
979
980
981
982 public Email setBounceAddress(String email)
983 {
984 this.bounceAddress = email;
985 return this;
986 }
987
988
989
990
991
992
993
994
995
996
997
998 public abstract Email setMsg(String msg) throws EmailException;
999
1000
1001
1002
1003
1004
1005
1006 public void buildMimeMessage() throws EmailException
1007 {
1008 try
1009 {
1010 this.getMailSession();
1011 this.message = new MimeMessage(this.session);
1012
1013 if (EmailUtils.isNotEmpty(this.subject))
1014 {
1015 if (EmailUtils.isNotEmpty(this.charset))
1016 {
1017 this.message.setSubject(this.subject, this.charset);
1018 }
1019 else
1020 {
1021 this.message.setSubject(this.subject);
1022 }
1023 }
1024
1025
1026
1027 if (this.content != null)
1028 {
1029 this.message.setContent(this.content, this.contentType);
1030 }
1031
1032
1033 else if (this.emailBody != null)
1034 {
1035 this.message.setContent(this.emailBody);
1036 }
1037 else
1038 {
1039 this.message.setContent("", Email.TEXT_PLAIN);
1040 }
1041
1042 if (this.fromAddress != null)
1043 {
1044 this.message.setFrom(this.fromAddress);
1045 }
1046 else
1047 {
1048 if (session.getProperty(MAIL_SMTP_FROM) == null)
1049 {
1050 throw new EmailException("From address required");
1051 }
1052 }
1053
1054 if (this.toList.size() + this.ccList.size() + this.bccList.size() == 0)
1055 {
1056 throw new EmailException(
1057 "At least one receiver address required");
1058 }
1059
1060 if (this.toList.size() > 0)
1061 {
1062 this.message.setRecipients(
1063 Message.RecipientType.TO,
1064 this.toInternetAddressArray(this.toList));
1065 }
1066
1067 if (this.ccList.size() > 0)
1068 {
1069 this.message.setRecipients(
1070 Message.RecipientType.CC,
1071 this.toInternetAddressArray(this.ccList));
1072 }
1073
1074 if (this.bccList.size() > 0)
1075 {
1076 this.message.setRecipients(
1077 Message.RecipientType.BCC,
1078 this.toInternetAddressArray(this.bccList));
1079 }
1080
1081 if (this.replyList.size() > 0)
1082 {
1083 this.message.setReplyTo(
1084 this.toInternetAddressArray(this.replyList));
1085 }
1086
1087 if (this.headers.size() > 0)
1088 {
1089 Iterator iterHeaderKeys = this.headers.keySet().iterator();
1090 while (iterHeaderKeys.hasNext())
1091 {
1092 String name = (String) iterHeaderKeys.next();
1093 String value = (String) headers.get(name);
1094 this.message.addHeader(name, value);
1095 }
1096 }
1097
1098 if (this.message.getSentDate() == null)
1099 {
1100 this.message.setSentDate(getSentDate());
1101 }
1102
1103 if (this.popBeforeSmtp)
1104 {
1105 Store store = session.getStore("pop3");
1106 store.connect(this.popHost, this.popUsername, this.popPassword);
1107 }
1108 }
1109 catch (MessagingException me)
1110 {
1111 throw new EmailException(me);
1112 }
1113 }
1114
1115
1116
1117
1118
1119
1120
1121 public String sendMimeMessage()
1122 throws EmailException
1123 {
1124 EmailUtils.notNull(this.message, "message");
1125
1126 try
1127 {
1128 Transport.send(this.message);
1129 return this.message.getMessageID();
1130 }
1131 catch (Throwable t)
1132 {
1133 String msg = "Sending the email to the following server failed : "
1134 + this.getHostName()
1135 + ":"
1136 + this.getSmtpPort();
1137
1138 throw new EmailException(msg, t);
1139 }
1140 }
1141
1142
1143
1144
1145
1146
1147
1148 public MimeMessage getMimeMessage()
1149 {
1150 return this.message;
1151 }
1152
1153
1154
1155
1156
1157
1158
1159
1160 public String send() throws EmailException
1161 {
1162 this.buildMimeMessage();
1163 return this.sendMimeMessage();
1164 }
1165
1166
1167
1168
1169
1170
1171
1172
1173 public void setSentDate(Date date)
1174 {
1175 this.sentDate = date;
1176 }
1177
1178
1179
1180
1181
1182
1183
1184 public Date getSentDate()
1185 {
1186 if (this.sentDate == null)
1187 {
1188 return new Date();
1189 }
1190 return this.sentDate;
1191 }
1192
1193
1194
1195
1196
1197
1198 public String getSubject()
1199 {
1200 return this.subject;
1201 }
1202
1203
1204
1205
1206
1207
1208 public InternetAddress getFromAddress()
1209 {
1210 return this.fromAddress;
1211 }
1212
1213
1214
1215
1216
1217
1218 public String getHostName()
1219 {
1220 if (EmailUtils.isNotEmpty(this.hostName))
1221 {
1222 return this.hostName;
1223 }
1224 else
1225 {
1226 return this.session.getProperty(MAIL_HOST);
1227 }
1228 }
1229
1230
1231
1232
1233
1234
1235 public String getSmtpPort()
1236 {
1237 if (EmailUtils.isNotEmpty(this.smtpPort))
1238 {
1239 return this.smtpPort;
1240 }
1241 else
1242 {
1243 return this.session.getProperty(MAIL_PORT);
1244 }
1245 }
1246
1247
1248
1249
1250
1251
1252
1253 public boolean isTLS()
1254 {
1255 return this.tls;
1256 }
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266 protected InternetAddress[] toInternetAddressArray(List list)
1267 {
1268 InternetAddress[] ia =
1269 (InternetAddress[]) list.toArray(new InternetAddress[list.size()]);
1270
1271 return ia;
1272 }
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284 public void setPopBeforeSmtp(
1285 boolean newPopBeforeSmtp,
1286 String newPopHost,
1287 String newPopUsername,
1288 String newPopPassword)
1289 {
1290 this.popBeforeSmtp = newPopBeforeSmtp;
1291 this.popHost = newPopHost;
1292 this.popUsername = newPopUsername;
1293 this.popPassword = newPopPassword;
1294 }
1295
1296
1297
1298
1299
1300 public boolean isSSL()
1301 {
1302 return ssl;
1303 }
1304
1305
1306
1307
1308
1309 public void setSSL(boolean ssl)
1310 {
1311 this.ssl = ssl;
1312 }
1313
1314
1315
1316
1317
1318 public String getSslSmtpPort()
1319 {
1320 if (EmailUtils.isNotEmpty(this.sslSmtpPort))
1321 {
1322 return this.sslSmtpPort;
1323 }
1324 else
1325 {
1326 return this.session.getProperty(MAIL_SMTP_SOCKET_FACTORY_PORT);
1327 }
1328 }
1329
1330
1331
1332
1333
1334
1335 public void setSslSmtpPort(String sslSmtpPort)
1336 {
1337 this.sslSmtpPort = sslSmtpPort;
1338 }
1339 }