implement very slow but working headers to hashmap
[antidote.git] / src / imap.vala
blob0e6a87e904f27cbf4fa8f5e5bad4935d52220ed6
1 /* FIXME: refactor the check response stuff */
2 /* FIXME: try to be doxygen conform */
3 /* FIXME: refactor a lot ;) */
4 using Gee;
6 namespace Antidote {
8 /* FIXME: use RFC Errors! */
9 errordomain IMAPError {
10 CONNECTION,
11 LOGIN,
12 LIST
15 /* message struct */
16 struct Message {
17 public string from;
18 public string to;
19 public string date;
20 public string subject;
21 public string full_header;
24 class IMAP {
25 public IMAP () {
26 logger = new Logger();
27 //FIXME: add if debug or something equal later!
28 logger.name= "Antidote:IMAP";
29 logger.log_level= logger.LogLevel.DEBUG;
32 private Logger logger;
33 private SocketConnection conn;
34 private SocketClient client = new SocketClient ();
35 private DataInputStream response;
36 private uint16 _q_id = 0;
38 public string host { get; set; }
39 public uint16 port { get; set; }
40 public string username { get; set; }
41 public string password { get; set; }
42 public bool ssl { get; set; }
44 public string next_q_id() {
45 return "a" + (_q_id++).to_string(); //overflows on purpose ;)
49 * Establish a connection to the server and keep it.
50 * Throw error if connection cannot be established.
52 public void connect() throws GLib.Error, IMAPError {
53 var resolver = Resolver.get_default();
54 var addresses = resolver.lookup_by_name(host, null);
55 var address = addresses.nth_data(0);
57 logger.log(logger.LogLevel.DEBUG,@"Resolved $host to $address\n");
59 if(ssl) {
60 client.set_tls(ssl);
61 client.set_tls_validation_flags(TlsCertificateFlags.UNKNOWN_CA);
62 logger.log(logger.LogLevel.DEBUG,"using ssl\n");
64 conn = client.connect(new InetSocketAddress (address, port));
66 logger.log(logger.LogLevel.DEBUG,@"Connected to $host\n");
68 /* Check response */
69 response = new DataInputStream (conn.input_stream);
70 var status_line = response.read_line(null);
71 if (!status_line.contains("OK")) {
72 throw new IMAPError.CONNECTION(status_line);
74 else {
75 logger.log(logger.LogLevel.DEBUG,status_line+"\n");
79 /* simple imap command wrapper */
80 private string imap_command(string command) throws GLib.Error, IMAPError {
81 var ret = "";
82 var q_id = next_q_id();
84 var message = @"$q_id $command\n";
85 conn.output_stream.write(message.data);
86 // logger.log(logger.LogLevel.DEBUG,message);
88 /* Check response */
89 var status_line = response.read_line(null);
90 if (status_line.contains(q_id + " NO") || status_line.contains("BAD"))
91 throw new IMAPError.LIST(status_line);
93 ret = status_line+"\n";
95 /* The command has a on line return value - we must return here! */
96 if (ret.contains(q_id + " OK"))
97 return ret;
99 //FIXME: NO responses?
100 while (!(status_line = response.read_line(null)).contains(q_id + " OK")) {
101 ret = ret + status_line+"\n";
104 // logger.log(logger.LogLevel.DEBUG,ret);
106 return ret;
109 /* login into account throw imap error LOGIN */
110 public void login() throws GLib.Error, IMAPError {
111 imap_command(@"LOGIN $username $password");
114 /* list dir */
115 public string list(string what) throws GLib.Error, IMAPError {
116 return imap_command(@"LIST \"\" \"$what\"");
119 /* examine dir */
120 public string examine(string what) throws GLib.Error, IMAPError {
121 return imap_command(@"EXAMINE $what");
124 /* fetch foo as string */
125 public string fetch(string start_uid,string end_uid,string what) throws GLib.Error, IMAPError {
126 return imap_command(@"FETCH $start_uid:$end_uid $what");
130 /* get thread */
131 public string thread(string algorithm,string char_set,string what) throws GLib.Error, IMAPError {
132 return imap_command(@"THREAD $algorithm $char_set $what");
135 /* get headers as hash map */
136 public HashMap<int,Message?> get_headers(string start_uid,string end_uid) {
137 var regex_to = new Regex ("""^To:*""");
138 var regex_from = new Regex ("""^From:*""");
139 var regex_subject = new Regex ("""^Subject:*""");
140 var regex_date = new Regex ("""^Date:*""");
141 var regex_uid = new Regex ("""HEADER""");
143 //FIXME: this code may take very long to complete!!!
144 var map = new HashMap<int,Message?> ();
145 string all = imap_command(@"FETCH $start_uid:$end_uid RFC822.HEADER");
146 var list = all.split("\n)");
148 foreach (string s in list) {
149 int uid= 0;
150 Message tmp = Message();
151 var lines = s.split("\n");
152 foreach (string line in lines ){
153 if (regex_uid.match(line)) {
154 var parts = line.split(" ");
155 uid=parts[1].to_int();
157 else if (regex_to.match(line))
158 tmp.to = line.replace("To: ","").strip();
159 else if (regex_from.match(line))
160 tmp.from = (string)line.replace("From: ","").strip();
161 else if (regex_subject.match(line))
162 tmp.subject = (string)line.replace("Subject: ","").strip();
163 else if (regex_date.match(line))
164 tmp.date = line.replace("Date: ","").strip();
167 /* only push the entry if we found a header in the string */
168 if(uid != 0) {
169 tmp.full_header = s;
170 map.set (uid,tmp);
174 return map;