Subversion Repositories javautils

Rev

Rev 3 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3 Rev 9
1
package de.viathinksoft.utils.mail;
1
package de.viathinksoft.utils.mail;
2
 
2
 
3
import java.net.IDN;
3
import java.net.IDN;
4
 
4
 
5
import de.viathinksoft.utils.mail.syntaxchecker.MailSyntaxChecker;
-
 
6
 
-
 
7
/**
5
/**
8
 *
6
 *
9
 * This class parses an email address (trims whitespaces from it) and stores it
7
 * This class parses an email address (trims whitespaces from it) and stores it
10
 * in its original form as well as store a RFC-compatible punycoded domainpart.
8
 * in its original form as well as store a RFC-compatible punycoded domainpart.
11
 * So, if you enter a Unicode-Mail-Address you can easily access the trimmed and
9
 * So, if you enter a Unicode-Mail-Address you can easily access the trimmed and
12
 * punycoded domain-part mail-address. Warning! This class does NOT check if the
10
 * punycoded domain-part mail-address. Warning! This class does NOT check if the
13
 * email address is fully valid. Please use the syntax checker class for this.
11
 * email address is fully valid. Please use the syntax checker class for this.
14
 *
12
 *
15
 * @author Daniel Marschall
13
 * @author Daniel Marschall
16
 *
14
 *
17
 */
15
 */
18
public class EMailAddress {
16
public class EMailAddress {
19
 
17
 
20
        // Constants
18
        // Constants
21
 
19
 
22
        /**
20
        /**
23
         * This constant is used by toString() and tells if whether
21
         * This constant is used by toString() and tells if whether
24
         * getMailAddressUnicode() or getMailAddressPunycodedDomain() should be
22
         * getMailAddressUnicode() or getMailAddressPunycodedDomain() should be
25
         * returned.
23
         * returned.
26
         */
24
         */
27
        static boolean USE_UNICODE_AS_STANDARD = false;
25
        static boolean USE_UNICODE_AS_STANDARD = false;
28
       
26
 
29
        // Attributes
27
        // Attributes
30
 
28
 
31
        /**
29
        /**
32
         * The local part of our parsed mail address. (Part before "@") It is
30
         * The local part of our parsed mail address. (Part before "@") It is
33
         * allways Unicode, since the mail servers have to take care about it. Even
31
         * allways Unicode, since the mail servers have to take care about it. Even
34
         * if Unicode mail addresses will become popular in future, the local part
32
         * if Unicode mail addresses will become popular in future, the local part
35
         * will probably not punycoded.
33
         * will probably not punycoded.
36
         */
34
         */
37
        private String localPart;
35
        private String localPart;
38
        /**
36
        /**
39
         * The domain part of our parsed mail address (part after "@") inclusive our
37
         * The domain part of our parsed mail address (part after "@") inclusive our
40
         * top level domain (TLD). It is in its Unicode form.
38
         * top level domain (TLD). It is in its Unicode form.
41
         */
39
         */
42
        private String domainPartUnicode;
40
        private String domainPartUnicode;
43
 
41
 
44
        /**
42
        /**
45
         * The domain part of our parsed mail address (part after "@") inclusive our
43
         * The domain part of our parsed mail address (part after "@") inclusive our
46
         * top level domain (TLD). It is in its Punycode (ASCII) form.
44
         * top level domain (TLD). It is in its Punycode (ASCII) form.
47
         */
45
         */
48
        private String domainPartPunycode;
46
        private String domainPartPunycode;
49
 
47
 
50
        /**
48
        /**
51
         * The top level domain (COM, ORG, BIZ...) of our parsed mail address. The
49
         * The top level domain (COM, ORG, BIZ...) of our parsed mail address. The
52
         * dot is not included. It is in its Unicode form.
50
         * dot is not included. It is in its Unicode form.
53
         */
51
         */
54
        private String tldUnicode;
52
        private String tldUnicode;
55
 
53
 
56
        /**
54
        /**
57
         * The top level domain (COM, ORG, BIZ...) of our parsed mail address. The
55
         * The top level domain (COM, ORG, BIZ...) of our parsed mail address. The
58
         * dot is not included. It is in its Punycode form.
56
         * dot is not included. It is in its Punycode form.
59
         */
57
         */
60
        private String tldPunycode;
58
        private String tldPunycode;
61
 
59
 
62
        // Getter and Setter
60
        // Getter and Setter
63
 
61
 
64
        /**
62
        /**
65
         * The local part of our parsed mail address. (Part before "@") It is
63
         * The local part of our parsed mail address. (Part before "@") It is
66
         * allways Unicode, since the mail servers have to take care about it. Even
64
         * allways Unicode, since the mail servers have to take care about it. Even
67
         * if Unicode mail addresses will become popular in future, the local part
65
         * if Unicode mail addresses will become popular in future, the local part
68
         * will probably not punycoded.
66
         * will probably not punycoded.
69
         *
67
         *
70
         * @return The local part
68
         * @return The local part
71
         */
69
         */
72
        public String getLocalPart() {
70
        public String getLocalPart() {
73
                return localPart;
71
                return localPart;
74
        }
72
        }
75
 
73
 
76
        /**
74
        /**
77
         * The domain part of our parsed mail address (part after "@") inclusive our
75
         * The domain part of our parsed mail address (part after "@") inclusive our
78
         * top level domain (TLD). It is in its Unicode form.
76
         * top level domain (TLD). It is in its Unicode form.
79
         *
77
         *
80
         * @return The domain part in Unicode.
78
         * @return The domain part in Unicode.
81
         */
79
         */
82
        public String getDomainPartUnicode() {
80
        public String getDomainPartUnicode() {
83
                return domainPartUnicode;
81
                return domainPartUnicode;
84
        }
82
        }
85
 
83
 
86
        /**
84
        /**
87
         * The domain part of our parsed mail address (part after "@") inclusive our
85
         * The domain part of our parsed mail address (part after "@") inclusive our
88
         * top level domain (TLD). It is in its Punycode (ASCII) form.
86
         * top level domain (TLD). It is in its Punycode (ASCII) form.
89
         *
87
         *
90
         * @return The domain part in Punycode.
88
         * @return The domain part in Punycode.
91
         */
89
         */
92
        public String getDomainPartPunycode() {
90
        public String getDomainPartPunycode() {
93
                return domainPartPunycode;
91
                return domainPartPunycode;
94
        }
92
        }
95
 
93
 
96
        /**
94
        /**
97
         * The top level domain (COM, ORG, BIZ...) of our parsed mail address. The
95
         * The top level domain (COM, ORG, BIZ...) of our parsed mail address. The
98
         * dot is not included. It is in its Unicode form.
96
         * dot is not included. It is in its Unicode form.
99
         *
97
         *
100
         * @return The TLD in Unicode.
98
         * @return The TLD in Unicode.
101
         */
99
         */
102
        public String getTldUnicode() {
100
        public String getTldUnicode() {
103
                return tldUnicode;
101
                return tldUnicode;
104
        }
102
        }
105
 
103
 
106
        /**
104
        /**
107
         * The top level domain (COM, ORG, BIZ...) of our parsed mail address. The
105
         * The top level domain (COM, ORG, BIZ...) of our parsed mail address. The
108
         * dot is not included. It is in its Punycode form.
106
         * dot is not included. It is in its Punycode form.
109
         *
107
         *
110
         * @return The TLD in Punycode.
108
         * @return The TLD in Punycode.
111
         */
109
         */
112
        public String getTldPunycode() {
110
        public String getTldPunycode() {
113
                return tldPunycode;
111
                return tldPunycode;
114
        }
112
        }
115
 
113
 
116
        // Constructors
114
        // Constructors
117
 
115
 
118
        /**
116
        /**
119
         * Creates an email address object out of an email address string.
117
         * Creates an email address object out of an email address string.
120
         *
118
         *
121
         * @param eMailAddress
119
         * @param eMailAddress
122
         *            bare computer email address. e.g. roedyg@mindprod.com No
120
         *            bare computer email address. e.g. roedyg@mindprod.com No
123
         *            "Roedy Green" <roedyg@mindprod.com> style addresses. No local
121
         *            "Roedy Green" <roedyg@mindprod.com> style addresses. No local
124
         *            addresses, e.g. roedy.
122
         *            addresses, e.g. roedy.
125
         * @throws InvalidMailAddressException
-
 
126
         */
123
         */
127
        public EMailAddress(String eMailAddress) throws InvalidMailAddressException {
124
        public EMailAddress(String eMailAddress) {
128
                super();
125
                super();
129
 
126
 
130
                if (eMailAddress == null) {
-
 
131
                        throw new InvalidMailAddressException();
-
 
132
                }
-
 
133
 
-
 
134
                // Zuerst trimmen (z.B. für Formulardaten) Wir splitten dann beim
127
                // Zuerst trimmen (z.B. für Formulardaten)
135
                // At-Zeichen (@) und berücksichtigen ein escaped-At
-
 
136
                // (\@)
-
 
137
                String[] res = eMailAddress.trim().split("(?<!\\\\)@");
128
                eMailAddress = eMailAddress.trim();
138
 
129
 
139
                // @-sign was not used once
130
                // Wir splitten dann beim At-Zeichen (@)
-
 
131
                String localPart = "";
-
 
132
                String domainPart = "";
-
 
133
                int atIndex = eMailAddress.lastIndexOf('@');
140
                if (res.length != 2) {
134
                if (atIndex == -1) {
-
 
135
                        localPart = eMailAddress;
-
 
136
                        domainPart = "";
-
 
137
                } else {
141
                        throw new InvalidMailAddressException();
138
                        localPart = eMailAddress.substring(0, atIndex);
-
 
139
                        domainPart = eMailAddress.substring(atIndex + 1);
142
                }
140
                }
143
 
141
 
144
                // Temporary we store the values here.
-
 
145
 
-
 
146
                String localPart = res[0];
-
 
147
                String domainPart = res[1];
-
 
148
 
-
 
149
                // We parse the local part.
142
                // We parse the local part.
150
 
143
 
151
                if (localPart == null)
144
                if (localPart == null)
152
                        localPart = "";
145
                        localPart = "";
153
                this.localPart = localPart;
146
                this.localPart = localPart;
154
 
147
 
155
                // We parse the domainPart and allocate punycode and unicode fields.
148
                // We parse the domainPart and allocate punycode and unicode fields.
156
 
149
 
157
                if (domainPart == null)
150
                if (domainPart == null)
158
                        domainPart = "";
151
                        domainPart = "";
159
                if (isUnicode(domainPart)) {
152
                if (isUnicode(domainPart)) {
160
                        this.domainPartUnicode = domainPart;
153
                        this.domainPartUnicode = domainPart;
161
                        this.domainPartPunycode = IDN.toASCII(domainPart);
154
                        this.domainPartPunycode = IDN.toASCII(domainPart);
162
                } else /* if (isPunycode(domainPart)) */{
155
                } else /* if (isPunycode(domainPart)) */{
163
                        this.domainPartUnicode = IDN.toUnicode(domainPart);
156
                        this.domainPartUnicode = IDN.toUnicode(domainPart);
164
                        this.domainPartPunycode = domainPart;
157
                        this.domainPartPunycode = domainPart;
165
                }
158
                }
166
 
159
 
167
                // We additionally parse the TLD and also determinate if it is punycode
160
                // We additionally parse the TLD and also determinate if it is punycode
168
                // or not.
161
                // or not.
169
 
162
 
170
                int dotIdx;
163
                int dotIdx;
171
 
164
 
172
                dotIdx = this.domainPartUnicode.lastIndexOf('.');
165
                dotIdx = this.domainPartUnicode.lastIndexOf('.');
173
                if (dotIdx >= 0) {
166
                if (dotIdx >= 0) {
174
                        this.tldUnicode = this.domainPartUnicode.substring(dotIdx + 1);
167
                        this.tldUnicode = this.domainPartUnicode.substring(dotIdx + 1);
175
                } else {
168
                } else {
176
                        // We do not throw an exception here because it could be an email to
169
                        // We do not throw an exception here because it could be an email to
177
                        // a network computer or an IP address.
170
                        // a network computer or an IP address.
178
                        this.tldUnicode = "";
171
                        this.tldUnicode = "";
179
                }
172
                }
180
 
173
 
181
                dotIdx = this.domainPartPunycode.lastIndexOf('.');
174
                dotIdx = this.domainPartPunycode.lastIndexOf('.');
182
                if (dotIdx >= 0) {
175
                if (dotIdx >= 0) {
183
                        this.tldPunycode = this.domainPartPunycode.substring(dotIdx + 1);
176
                        this.tldPunycode = this.domainPartPunycode.substring(dotIdx + 1);
184
                } else {
177
                } else {
185
                        // We do not throw an exception here because it could be an email to
178
                        // We do not throw an exception here because it could be an email to
186
                        // a network computer or an IP address.
179
                        // a network computer or an IP address.
187
                        this.tldPunycode = "";
180
                        this.tldPunycode = "";
188
                }
181
                }
189
        }
182
        }
190
 
183
 
191
        // Methods
184
        // Methods
192
 
185
 
193
        /**
186
        /**
194
         * Returns the email address with punycoded domain name and TLD. You should use
187
         * Returns the email address with punycoded domain name and TLD. You should
195
         * this method to send emails.
188
         * use this method to send emails.
196
         *
189
         *
197
         * @return The email address with punycoded domain name and TLD.
190
         * @return The email address with punycoded domain name and TLD.
198
         */
191
         */
199
        public String getMailAddressPunycodedDomain() {
192
        public String getMailAddressPunycodedDomain() {
-
 
193
                if (this.domainPartPunycode.equals("")) {
-
 
194
                        return this.localPart;
-
 
195
                } else {
200
                return this.localPart + "@" + this.domainPartPunycode;
196
                        return this.localPart + "@" + this.domainPartPunycode;
201
        }
197
                }
-
 
198
        }
202
 
199
 
203
        /**
200
        /**
204
         * Returns the email address with internationalized domain names and TLD.
201
         * Returns the email address with internationalized domain names and TLD.
205
         *
202
         *
206
         * @return The email address with internationalized domain name and TLD.
203
         * @return The email address with internationalized domain name and TLD.
207
         */
204
         */
208
        public String getMailAddressUnicode() {
205
        public String getMailAddressUnicode() {
-
 
206
                if (this.domainPartUnicode.equals("")) {
-
 
207
                        return this.localPart;
-
 
208
                } else {
209
                return this.localPart + "@" + this.domainPartUnicode;
209
                        return this.localPart + "@" + this.domainPartUnicode;
210
        }
210
                }
-
 
211
        }
211
 
212
 
212
        /**
213
        /**
213
         * Returns a string which represents the mail address. If the constant
214
         * Returns a string which represents the mail address. If the constant
214
         * USE_UNICODE_AS_STANDARD is true, the internationalized domain names will
215
         * USE_UNICODE_AS_STANDARD is true, the internationalized domain names will
215
         * not translated into the corresponding Punycode. If false, then not.
216
         * not translated into the corresponding Punycode. If false, then not.
216
         *
217
         *
217
         * @return The string which represents the mail address. Warning! Since this
218
         * @return The string which represents the mail address. Warning! Since this
218
         *         method is rather designed to show a formatted mail address, it
219
         *         method is rather designed to show a formatted mail address, it
219
         *         should NOT be used to send emails. Please only use this function
220
         *         should NOT be used to send emails. Please only use this function
220
         *         if you want to output.
221
         *         if you want to output.
221
         */
222
         */
222
        @Override
223
        @Override
223
        public String toString() {
224
        public String toString() {
224
                if (USE_UNICODE_AS_STANDARD) {
225
                if (USE_UNICODE_AS_STANDARD) {
225
                        return this.getMailAddressUnicode();
226
                        return this.getMailAddressUnicode();
226
                } else {
227
                } else {
227
                        return this.getMailAddressPunycodedDomain();
228
                        return this.getMailAddressPunycodedDomain();
228
                }
229
                }
229
        }
230
        }
230
 
231
 
231
        /**
232
        /**
232
         * Checks if an object is equal to our email address object.
233
         * Checks if an object is equal to our email address object.
233
         *
234
         *
234
         * @return Boolean which describes if it is equal or not.
235
         * @return Boolean which describes if it is equal or not.
235
         */
236
         */
236
        @Override
237
        @Override
237
        public boolean equals(Object obj) {
238
        public boolean equals(Object obj) {
238
                // Initial checks
239
                // Initial checks
239
 
240
 
240
                if (this == obj)
241
                if (this == obj)
241
                        return true;
242
                        return true;
242
                if (obj == null)
243
                if (obj == null)
243
                        return false;
244
                        return false;
244
                if (obj.getClass() != getClass())
245
                if (obj.getClass() != getClass())
245
                        return false;
246
                        return false;
246
 
247
 
247
                // Compare the fields
248
                // Compare the fields
248
 
249
 
249
                if (!this.domainPartPunycode
250
                if (!this.domainPartPunycode
250
                                .equals(((EMailAddress) obj).domainPartPunycode)) {
251
                                .equals(((EMailAddress) obj).domainPartPunycode)) {
251
                        return false;
252
                        return false;
252
                }
253
                }
253
                if (!this.domainPartUnicode
254
                if (!this.domainPartUnicode
254
                                .equals(((EMailAddress) obj).domainPartUnicode)) {
255
                                .equals(((EMailAddress) obj).domainPartUnicode)) {
255
                        return false;
256
                        return false;
256
                }
257
                }
257
                if (!this.localPart.equals(((EMailAddress) obj).localPart)) {
258
                if (!this.localPart.equals(((EMailAddress) obj).localPart)) {
258
                        return false;
259
                        return false;
259
                }
260
                }
260
                if (!this.tldUnicode.equals(((EMailAddress) obj).tldUnicode)) {
261
                if (!this.tldUnicode.equals(((EMailAddress) obj).tldUnicode)) {
261
                        return false;
262
                        return false;
262
                }
263
                }
263
                if (!this.tldPunycode.equals(((EMailAddress) obj).tldPunycode)) {
264
                if (!this.tldPunycode.equals(((EMailAddress) obj).tldPunycode)) {
264
                        return false;
265
                        return false;
265
                }
266
                }
266
 
267
 
267
                // Everything's fine ^^
268
                // Everything's fine ^^
268
 
269
 
269
                return true;
270
                return true;
270
 
271
 
271
                // return this.toString().equals(obj.toString());
272
                // return this.toString().equals(obj.toString());
272
        }
273
        }
273
 
274
 
274
        /**
275
        /**
275
         * Creates a deep copy of the email address object.
276
         * Creates a deep copy of the email address object.
276
         *
277
         *
277
         * @return A new instance of the email address object with the same
278
         * @return A new instance of the email address object with the same
278
         *         properties.
279
         *         properties.
279
         */
280
         */
280
        @Override
281
        @Override
281
        protected EMailAddress clone() throws CloneNotSupportedException {
282
        protected EMailAddress clone() throws CloneNotSupportedException {
282
                try {
-
 
283
                        return new EMailAddress(this.toString());
283
                return new EMailAddress(this.toString());
284
                } catch (InvalidMailAddressException e) {
-
 
285
                        return null;
-
 
286
                }
-
 
287
        }
-
 
288
 
-
 
289
        /**
-
 
290
         * Asks the mail syntax checker if the current mail address is valid or not.
-
 
291
         * Warning! This check is NOT performed automatically. There is no guarantee
-
 
292
         * that the syntax check is 100% correct. There might be mail address which
-
 
293
         * are valid but marked as invalid (because server disobeyed RFC rules etc)
-
 
294
         * and mail addresses which are invalid but marked valid (e.g. simply if
-
 
295
         * they were not assigned).
-
 
296
         *
-
 
297
         * @return Boolean which represents if the mail address is valid or not.
-
 
298
         */
-
 
299
        public boolean isSyntaxValid() {
-
 
300
                return MailSyntaxChecker.isMailValid(this);
-
 
301
        }
284
        }
302
 
285
 
303
        // ---------- STATIC FUNCTIONS ----------
286
        // ---------- STATIC FUNCTIONS ----------
304
 
287
 
305
        /**
288
        /**
306
         * Determinates if a given string can be converted into Punycode.
289
         * Determinates if a given string can be converted into Punycode.
307
         *
290
         *
308
         * @param str
291
         * @param str
309
         *            The string which should be checked
292
         *            The string which should be checked
310
         * @return Boolean which shows if the string is not yet punicoded.
293
         * @return Boolean which shows if the string is not yet punicoded.
311
         */
294
         */
312
        protected static boolean isUnicode(String str) {
295
        protected static boolean isUnicode(String str) {
313
                if (str == null)
296
                if (str == null) {
314
                        return false;
297
                        return false;
-
 
298
                }
315
                return (!IDN.toASCII(str).equals(str));
299
                return (!IDN.toASCII(str).equals(str));
316
        }
300
        }
317
 
301
 
318
        /**
302
        /**
319
         * Determinates if a given string is in Punycode format.
303
         * Determinates if a given string is in Punycode format.
320
         *
304
         *
321
         * @param str
305
         * @param str
322
         *            The string which should be checked
306
         *            The string which should be checked
323
         * @return Boolean which shows if the string is punycoded or not.
307
         * @return Boolean which shows if the string is punycoded or not.
324
         */
308
         */
325
        protected static boolean isPunycode(String str) {
309
        protected static boolean isPunycode(String str) {
326
                if (str == null)
310
                if (str == null) {
327
                        return false;
311
                        return false;
-
 
312
                }
328
                return (!IDN.toUnicode(str).equals(str));
313
                return (!IDN.toUnicode(str).equals(str));
329
        }
314
        }
330
}
315
}
331
 
316