1 /* FIXME: refactor the check response stuff */
2 /* FIXME: try to be doxygen conform */
3 /* FIXME: refactor a lot ;) */
8 /* FIXME: use RFC Errors! */
9 errordomain IMAPError
{
20 public string subject
;
21 public string full_header
;
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");
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");
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
);
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
{
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);
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"))
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);
109 /* login into account throw imap error LOGIN */
110 public void login() throws GLib
.Error
, IMAPError
{
111 imap_command(@
"LOGIN $username $password");
115 public string list(string what
) throws GLib
.Error
, IMAPError
{
116 return imap_command(@
"LIST \"\" \"$what\"");
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");
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
) {
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 */