1 module skoenlapper.client;
2 
3 import std.stdio;
4 import skoenlapper.configurator;
5 import libutterfly.client;
6 import libutterfly.exceptions;
7 import gogga;
8 import std.conv : to;
9 import std.json;
10 import std.file : exists, mkdir;
11 import core.thread : Thread, dur;
12 import std.socket : Address;
13 
14 /*  */
15 void viewMail(string[] mailPaths, string configFile, ulong accountIndex = 0)
16 {
17     /* Read in configurstion */
18     Configuration configuration = new Configuration(getConfiguration(configFile));
19 
20     /* Get the account to be used (TODO: Bounds check) */
21     Account chosenAccount = configuration.getAccount(accountIndex);
22 
23     /* Read in the mail message */
24     File mailFile;
25     mailFile.open(mailPaths[0]);
26     byte[] mailData;
27     mailData.length = mailFile.size();
28     mailData = mailFile.rawRead(mailData);
29     mailFile.close();
30 
31     /* Display the mail message */
32     JSONValue mailMessage = parseJSON(cast(string)mailData);
33     writeln("From: "~mailMessage["from"].str());
34     writeln("Subject: "~mailMessage["subject"].str()~"\n");
35     writeln(mailMessage["body"].str());
36 
37     /* TODO: Read stdin here for next line */
38 }
39 
40 
41 /**
42 * Runs the mail daemon which creates a local directory
43 * structure mirroring that of the server's mailbox,
44 * filling each folder and sub-folder with ist respective
45 * contents and watching for any new mail that comes in
46 *
47 * Assumes that the first active account is to be used (this can be changed)addresses
48 */
49 void mailDaemon(string configFile, ulong accountIndex = 0)
50 {
51     /* Read in configurstion */
52     Configuration configuration = new Configuration(getConfiguration(configFile));
53 
54     /* Get the account to be used (TODO: Bounds check) */
55     Account chosenAccount = configuration.getAccount(accountIndex);
56 
57     /* Authenticate a new session (TODO: Error handling in library and then catch here) */
58     gprintln("Opening connection to "~to!(string)(chosenAccount.getServer()));
59     ButterflyClient client = new ButterflyClient(chosenAccount.getServer());
60 
61     /* Authenticate (TODO: Error) */
62     gprintln("Authenticating with server...");
63     client.authenticate(chosenAccount.getUsername(), chosenAccount.getPassword());
64 
65     string[] root = client.listFolder("/");
66     gprintln("Found folders: "~to!(string)(root));
67 
68     /* Check if the directory for this account exists (if not then create it) */
69     if(!exists(chosenAccount.getMailbox()))
70     {
71         mkdir(chosenAccount.getMailbox());
72     }
73 
74     /* Preiodically check for new mail */
75     while(true)
76     {
77         /* Create folder structure every now and then (skipping already present stuff) */
78         gprintln("Starting mail check cycle...");
79         createFolderStructures(chosenAccount.getMailbox(), "/", client);
80         gprintln("Mail check cycle completed");
81         Thread.sleep(dur!("seconds")(5));
82     }
83 }
84 
85 /**
86 * Creates the folder structure in the mailbox for the 
87 * specified account
88 */
89 void createFolderStructures(string mailboxDirectory, string currentFolder, ButterflyClient client)
90 {
91     /* Get all folders */
92     string[] folders = client.listFolder(currentFolder);
93 
94     /* Loop through each directory of the current `root` */
95     foreach(string directory; folders)
96     {
97         /* Create the directory */
98         gprintln("Checking for local directory for remote directory '"~directory~"'...");
99         if(!exists(mailboxDirectory~currentFolder~"/"~directory))
100         {
101             gprintln("Creating local directory for remote directory '"~directory~"'...");
102             mkdir(mailboxDirectory~currentFolder~"/"~directory);
103         }
104 
105         /* List all mail in the current folder */
106         string[] mailIDs = client.listMail(currentFolder~"/"~directory);
107         foreach(string mailID; mailIDs)
108         {
109             /* If the mail exists then skip it */
110             if(exists(mailboxDirectory~currentFolder~"/"~directory~"/"~mailID))
111             {
112                 continue;
113             }
114 
115             /* Fetch the mail message */
116             gprintln("Fetching mail message '"~mailID~"'...");
117             string mail = client.fetchMail(currentFolder~"/"~directory, mailID).toPrettyString();
118 
119             /* Store mail message */
120             File file;
121             file.open(mailboxDirectory~currentFolder~"/"~directory~"/"~mailID, "wb");
122             file.rawWrite(cast(byte[])mail);
123             file.close();
124         }
125 
126         /* TODO: Clean up any mail no longer present on server */
127         /* TODO: Clean up any folders no longer present on server */
128 
129         /* Do the same on the current folder */
130         createFolderStructures(mailboxDirectory, currentFolder~"/"~directory, client);
131     }
132 }
133 
134 /**
135 * Sends mail provided the subject, address(es) and body
136 *
137 * Assumes that the first active account is to be used (this can be changed)addresses
138 */
139 void sendMail(string configFile, string subject, string[] addresses, string bodyText, ulong accountIndex = 0)
140 {
141     /* Read in configurstion */
142     Configuration configuration = new Configuration(getConfiguration(configFile));
143 
144     /* Get the account to be used (TODO: Bounds check) */
145     Account chosenAccount = configuration.getAccount(accountIndex);
146 
147     /* Authenticate a new session (TODO: Error handling in library and then catch here) */
148     gprintln("Opening connection to "~to!(string)(chosenAccount.getServer()));
149     ButterflyClient client = new ButterflyClient(chosenAccount.getServer());
150 
151     /* Authenticate (TODO: Error) */
152     gprintln("Authenticating with server...");
153     client.authenticate(chosenAccount.getUsername(), chosenAccount.getPassword());
154 
155     /* Construct the mail */
156     JSONValue mailMessage;
157     mailMessage["recipients"] = parseJSON(to!(string)(addresses));
158     mailMessage["subject"] = subject;
159     mailMessage["body"] = bodyText;
160 
161     /* Send the mail */
162     gprintln("Sending mail...");
163     client.sendMail(mailMessage);
164     gprintln("Mail sent!");
165 }
166 
167 string composeMail()
168 {
169     /* Read in from the tty */
170 	File tty;
171 	tty.open("/dev/stdin", "rb");
172 
173 	/* Body lines */
174 	string bodyLines;
175 
176 	while(true)
177 	{
178 		/* Read in 30-bute strides */
179 		byte[] bodyLine;
180 		bodyLine.length = 30;
181 
182 		/* Read a line */
183 		bodyLine = tty.rawRead(bodyLine);
184 				
185 		/**
186 		* Read returns then we are done reading, either the bodyLine.length
187 		* is non-zero but if it is zero then nothing was read (hence an EOF)
188 		* signal
189 		*/
190 		if(bodyLine.length == 0)
191 		{
192             /* Close the file and stop loop */
193             tty.close();
194 			break;
195 		}	
196 
197 		/* Store the line */
198 		bodyLines ~= bodyLine;
199 	}
200 
201     return bodyLines;
202 }
203 
204 /**
205 * Register
206 */
207 void register(Address server, string username, string password)
208 {
209     /* Open a new session (TODO: Error handling in library and then catch here) */
210     gprintln("Opening connection to "~to!(string)(server));
211     ButterflyClient client = new ButterflyClient(server);
212 
213     /* Register (TODO: Error) */
214     gprintln("Registering with server...");
215     try
216     {
217         client.register(username, password);
218         gprintln("Registration succeeded");
219     }
220     catch(ButterflyException e)
221     {
222         gprintln("Registration failed", DebugType.ERROR);
223     }
224 
225     /* TODO: Perhaps add an entry to the configuration file */
226 }