1 /* Copyright (C) 2000-2004 Thomas Bopp, Thorsten Hampel, Ludger Merkens
2 * Copyright (C) 2002 Christian Schmidt
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * $Id: mailbox.pike,v 1.1 2008/03/31 13:39:57 exodusd Exp $
20 inherit "/kernel/module";
21 inherit "/net/coal/binary";
23 #include <exception.h>
24 #include <attributes.h>
26 //! This module simulates a Mailbox for use with pop3 and imap4
27 //! That is normal sTeam documents are kept inside the Mailbox,
28 //! but Access of them is encapsulated by some functions.
29 class mailbox : public module,binary{
36 //Flags stored for each mail, also needed in net/imap.pike !!
38 #define ANSWERED (1<<1)
39 #define FLAGGED (1<<2)
40 #define DELETED (1<<3)
46 string sServer = _Server->query_config("machine");
47 string sDomain = _Server->query_config("domain");
48 string sFQDN = sServer+"."+sDomain;
53 mapping mMessages = ([ ]);
56 mapping (int:int) mMessageNums=([]);
59 void create(object o) {
66 //return flags of message(num)
67 int get_flags(int num)
69 array inv = oMailBox->get_inventory();
70 int flags=inv[num]->query_attribute(MAIL_IMAPFLAGS);
74 //set flags of message(num), overwrite existing flags
75 int set_flags(int num, int flags)
77 array inv = oMailBox->get_inventory();
78 mixed err = catch { inv[num]->set_attribute(MAIL_IMAPFLAGS,flags); };
79 if (err==0) return inv[num]->query_attribute(MAIL_IMAPFLAGS);
83 //add flags to message(num), keep existing flags
84 int add_flags(int num, int flags)
86 array inv = oMailBox->get_inventory();
87 int tflags=get_flags(num);
88 tflags = tflags | flags;
90 set_flags(num,tflags);
91 if(!has_flag(num,flags))
92 set_flags(num,flags); //attribute was not set before
95 //remove given flags from message(num)
96 int del_flags(int num, int flags)
98 array inv = oMailBox->get_inventory();
99 int tflags=get_flags(num);
100 tflags = tflags & (~flags); //"substract" flags from tflags
102 return set_flags(num,tflags);
105 //check if a flag is set or not
106 int has_flag(int num,int flag)
108 return( get_flags(num) & flag );
111 //returns the internal date of a message
112 int message_internal_date(int num)
114 array inv = oMailBox->get_inventory();
115 return inv[num]->query_attribute(OBJ_CREATION_TIME);
118 //get the rfc2822-headers of a message
119 mapping(string:string) message_headers(int num)
121 array inv = oMailBox->get_inventory();
123 if(zero_type(inv[num]->query_attribute(MAIL_MIMEHEADERS)))
124 add_header(num); //no headers found, create them now
126 return inv[num]->query_attribute(MAIL_MIMEHEADERS);
129 //check if a message has a rfc822-header
130 int has_header(int num)
132 array inv = oMailBox->get_inventory();
133 return !zero_type(inv[num]->query_attribute(MAIL_MIMEHEADERS));
136 //add a rfc822-header to a message
137 void add_header(int num, int|void force)
139 if(has_header(num) && !force)
141 LOG("Message #:"+num+" already has rfc822 data - add_header() aborted!");
145 array inv = oMailBox->get_inventory();
146 mapping(string:string) mHeader=([]);
149 LOG("creating rfc822-header for msg #"+num);
150 tmp=inv[num]->query_attribute(OBJ_NAME);
151 mHeader+=(["subject":tmp]);
153 tmp=ctime(inv[num]->query_attribute(OBJ_CREATION_TIME))-"\n";
154 mHeader+=(["date":tmp]);
156 tmp=inv[num]->query_attribute(DOC_USER_MODIFIED)->get_identifier();
157 string fullname = inv[num]->query_attribute(DOC_USER_MODIFIED)->query_attribute(USER_FULLNAME);
158 tmp="\""+fullname+"\" <"+tmp+"@"+sFQDN+">";
159 mHeader+=(["from":tmp]);
161 tmp=inv[num]->query_attribute(DOC_MIME_TYPE);
162 mHeader+=(["content-type":tmp]);
164 LOG(sprintf("%O",mHeader));
165 inv[num]->set_attribute(MAIL_MIMEHEADERS,mHeader);
166 LOG("added rfc822-header to msg #"+num);
169 //returns the body of a message
170 string message_body(int num)
172 array inv = oMailBox->get_inventory();
173 return inv[num]->get_content();
176 //converts a sequence of uids to message sequence numbers
177 array uid_to_num(array uids)
180 mapping(int:int) temp=([]);
181 array inv = oMailBox->get_inventory();
182 for(int i=0;i<sizeof(inv);i++)
183 temp+=([inv[i]->get_object_id():i]); //maps uids to sequence numbers
186 if(zero_type(temp[i])!=1) res+=({temp[i]+1});
191 mapping(int:int) get_uid2msn_mapping()
193 array inv = oMailBox->get_inventory();
194 mapping(int:int) temp=([]);
195 for(int i=0;i<sizeof(inv);i++)
196 temp+=([inv[i]->get_object_id():i+1]);
200 //logs some statistics for a specific mailbox
204 LOG("init_mailbox() ...");
205 array inv = oMailBox->get_inventory();
206 for (int i=0; i<sizeof(inv); i++)
208 mMessageNums+=([inv[i]->get_object_id():i]);
209 LOG(i+": #"+inv[i]->get_object_id()+", Flags: "+get_flags(i));
212 LOG("WARNING! Message #"+i+" has no header-data!");
216 LOG("init_mailbox() complete");
221 //returns a complete message, needed for pop3
222 object fetch_message(int num)
224 if ( objectp(mMessages[num]) )
225 return mMessages[num];
226 array inv = oMailBox->get_inventory();
227 mMessages[num] = oMessages->fetch_message(inv[num]);
228 return mMessages[num];
231 //delete all mails marked by 'delete_message()', only for pop3
234 foreach(to_delete, object del)
238 //delete all mails flagged 'deleted' (imap4)
239 //all connected imap-clients are notified via event-system
242 array inv = oMailBox->get_inventory();
243 for(int i=sizeof(inv)-1;i>=0;i--)
245 if(has_flag(i,DELETED))
249 _SECURITY->access_delete(0, msg, msg);
259 //returns the number of messages in a mailbox
260 int get_num_messages()
262 return sizeof(oMailBox->get_inventory());
265 //size of a message (header + body)
266 int get_message_size(int num)
268 array inv=oMailBox->get_inventory();
269 mapping(string:string) headers=inv[num]->query_attribute(MAIL_MIMEHEADERS);
271 // if(zero_value(inv[num]->query_attribute(MAIL_MIMEHEADERS))!=1)
273 foreach(indices(headers),string key)
274 dummy+=key+": "+headers[key]+"\r\n";
278 return inv[num]->get_content_size() + sizeof(dummy);
281 //size of a message-body (without header)
282 int get_body_size(int num)
284 array inv=oMailBox->get_inventory();
285 return inv[num]->get_content_size();
288 //message id for pop3
289 string get_message_id(int num)
291 int char_min = 0x21; // 33
292 int char_max = 0x7E; // 126
293 array inv = oMailBox->get_inventory();
294 int id = inv[num]->get_object_id();
295 string binary_str = send_binary(id);
296 return MIME.encode_base64(binary_str);
299 //message uid for imap4
300 int get_message_uid(int num)
302 array inv = oMailBox->get_inventory();
303 return inv[num]->get_object_id();
306 //size of all messages in the mailbox
309 array inv = oMailBox->get_inventory();
311 for ( int i = sizeof(inv) - 1; i >= 0; i-- ) {
312 sz += get_message_size(i);
317 //mark a message as deletet (only for pop3)
318 bool delete_message(int num)
320 array inv = oMailBox->get_inventory();
321 object msg = inv[num];
323 _SECURITY->access_delete(0, msg, msg);
326 LOG("Error: " + err[0] + "\n"+sprintf("%O", err));
329 to_delete += ({ msg });
336 int get_object_id() {
337 return oMailBox->get_object_id();
340 //returns a message as one string (for pop3)
342 string retrieve_message(int num) {
343 object msg = fetch_message(num);
353 oMessages = _Server->get_module("message");
354 set_attribute(OBJ_DESC, "This module functions as a pop3 and imap4 "+
355 "server for getting the users mailbox content to the mailreader "+
361 object get_mailbox(object user)
363 object mb = user->query_attribute(USER_MAILBOX);
369 string get_identifier() { return "mailbox"; }