1 module dcorelib.valueobjects.emailaddress;
2 
3 import dcorelib.valueobjects.constrainedstring;
4 import std.string;
5 import std.stdio;
6 
7 class EmailAddress : ConstrainedString
8 {
9     this(string newValue, string identifier) @safe
10     {
11         // An email address must not exceed 254 characters in length.
12         // https://stackoverflow.com/questions/386294/what-is-the-maximum-length-of-a-valid-email-address#574698
13         super(newValue, 254, false, identifier);
14 
15         if (!this.empty()) {
16             if (!this.emailAddressLooksValid(this.value)) {
17                 throw new Exception(format("%s does not appear to be a valid email address", identifier));
18             }
19         }
20     }
21 
22     private bool emailAddressLooksValid(in ref string emailAddress) @safe
23     {
24         // Ensure there is at @ symbol and that the @ symbol is not the first character
25         auto atPos = indexOf(emailAddress, "@");
26         if (atPos <= 0) {
27             return false;
28         }
29 
30         // Ensure there is not a second @ symbol
31         auto atPos2 = indexOf(emailAddress, "@", atPos + 1);
32         if (atPos2 > 0) {
33             return false;
34         }
35 
36         // Ensure there is a dot after the the at symbol
37         auto dotPos = indexOf(emailAddress, ".", atPos + 2);
38         if (dotPos <= 0) {
39             return false;
40         }
41 
42         // Ensure the dotPost is not the last OR second last character
43         if(dotPos >= emailAddress.length - 2) {
44             return false;
45         }
46 
47         return true;
48     }     
49 }
50 
51 unittest {
52     /********************** UNIT TESTS THAT SHOULD FAIL ********************/
53     try {
54         auto email = new EmailAddress("aaaaaa.com", "email");
55         assert(false, "Was able to create an Email address without an @ symbol");
56     } catch(Exception e) {
57 
58     }
59 
60     try {
61         auto email = new EmailAddress("aaaaaa@com", "email");
62         assert(false, "Was able to create an Email address without a . symbol");
63     } catch(Exception e) {
64 
65     }
66 
67     try {
68         auto email = new EmailAddress("aaaaaa@hello.", "email");
69         assert(false, "Was able to create an Email address with a . symbol in the wrong position");
70     } catch(Exception e) {
71 
72     }
73 
74     try {
75         auto email = new EmailAddress("aaaaaa@hello.c", "email");
76         assert(false, "Was able to create an Email address with a domain suffix that is too short");
77     } catch(Exception e) {
78 
79     }
80 
81     try {
82         auto email = new EmailAddress("aaaaaa@hello@another.co", "email");
83         assert(false, "Was able to create an Email address with a second @ symbol");
84     } catch(Exception e) {
85 
86     }    
87 
88     /********************** UNIT TESTS THAT SHOULD PASS ********************/
89     auto email1 = new EmailAddress("aaaaaa@hello.com", "email");
90     assert(email1.toString() == "aaaaaa@hello.com");
91 
92     auto email2 = new EmailAddress("a@h.co", "email");
93     assert(email2.toString() == "a@h.co");    
94 }