Subversion Repositories javautils

Rev

Rev 17 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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