[FIX] removed bad and useless call to ping (this is not a correct way of checking...
[odoo/odoo.git] / addons / smtpclient / smtpclient.py
1 ##############################################################################
2 #    
3 #    OpenERP, Open Source Management Solution
4 #    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
5 #
6 #    This program is free software: you can redistribute it and/or modify
7 #    it under the terms of the GNU Affero General Public License as
8 #    published by the Free Software Foundation, either version 3 of the
9 #    License, or (at your option) any later version.
10 #
11 #    This program is distributed in the hope that it will be useful,
12 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 #    GNU Affero General Public License for more details.
15 #
16 #    You should have received a copy of the GNU Affero General Public License
17 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.     
18 #
19 ##############################################################################
20
21 import os
22 import sys
23 import bz2
24
25 import time
26 from datetime import datetime
27 from datetime import timedelta
28
29 import release
30 import socket
31
32 import base64
33 import binascii
34
35 import random
36 import smtplib
37 import mimetypes
38
39 from email import Encoders
40 from optparse import OptionParser
41 from email.Message import Message
42 from email.MIMEBase import MIMEBase
43 from email.MIMEText import MIMEText
44 from email.MIMEMultipart import MIMEMultipart
45 from email.Utils import COMMASPACE, formatdate
46
47 import netsvc
48 import pooler
49 import tools
50
51 from osv import fields
52 from osv import osv
53 from tools.translate import _
54
55 error_msg = {
56     'not_active' : "Please activate Email Server, without activating you can not send Email(s).",
57     'server_stop' : 'Please start Email Server, without starting  you can not send Email(s).',
58     'server_not_confirm' : 'Please Verify Email Server, without verifying you can not send Email(s).'
59 }
60
61 logger = netsvc.Logger()
62
63 class smtpclient(osv.osv):
64
65     _name = 'email.smtpclient'
66     _description = 'Email Client'
67     
68     _columns = {
69         'name' : fields.char('Server Name', size=256, required=True),
70         'from_email' : fields.char('Email From', size=256),
71         'email' : fields.char('Email Address', size=256, required=True, readonly=True, states={'new':[('readonly',False)]}),
72         'user' : fields.char('User Name', size=256, readonly=True, states={'new':[('readonly',False)]}),
73         'password' : fields.char('Password', size=1024, invisible=True, readonly=True, states={'new':[('readonly',False)]}),
74         'server' : fields.char('SMTP Server', size=256, required=True, readonly=True, states={'new':[('readonly',False)]}),
75         'auth' : fields.boolean("Use Auth", readonly=True, states={'new':[('readonly',False)]}),
76         'port' : fields.char('SMTP Port', size=256, required=True, readonly=True, states={'new':[('readonly',False)]}),
77         'ssl' : fields.boolean("Use SSL?", readonly=True, states={'new':[('readonly',False)]}),
78         'users_id': fields.many2many('res.users', 'res_smtpserver_group_rel', 'sid', 'uid', 'Users Allowed'),
79         'state': fields.selection([
80             ('new','Not Verified'),
81             ('waiting','Waiting for Verification'),
82             ('confirm','Verified'),
83         ],'Server Status', select=True, readonly=True),
84         'auth_type':fields.selection([('gmail','Google Server'), ('yahoo','Yahoo!!! Server'), ('unknown','Other Mail Servers')], string="Server Type", readonly=True, states={'new':[('readonly',False)]}),
85         'active' : fields.boolean("Active"),
86         'date_create': fields.date('Date Create', required=True, readonly=True),
87         'test_email' : fields.text('Test Message', translate=True),
88         'body' : fields.text('Message', translate=True, help="The message text that will be send along with the email which is send through this server"),
89         'verify_email' : fields.text('Verify Message', translate=True, readonly=True, states={'new':[('readonly',False)]}),
90         'code' : fields.char('Verification Code', size=1024),
91         'type' : fields.selection([("default", "Default"),("account", "Account"),("sale","Sale"),("stock","Stock")], "Server Type",required=True),
92         'history_line': fields.one2many('email.smtpclient.history', 'server_id', 'History'),
93         'server_statistics': fields.one2many('report.smtp.server', 'server_id', 'Statistics'),
94         'delete_queue': fields.selection([
95             ('never','Never Delete Message'),
96             ('content','Delete Content After'),
97             ('all','Clear All After'),
98             ('after_send','Delete when Email Sent'),
99         ],'Queue Option', select=True),
100         'priority': fields.integer('Server Priority', readonly=True, states={'new':[('readonly',False)]}, help="Priority between 0 to 10, will be used to define the MTA process priotiry"),
101         'header_ids':fields.one2many('email.headers', 'server_id', 'Default Headers'),
102         'disclaimers': fields.text('Disclaimers'),
103         'process_id': fields.many2one('ir.cron', 'MTA Process', readonly=True, help="Mail Transport Agent Process"),
104         'pstate': fields.selection([
105             ('running','Running'),
106             ('stop','Stop'),
107         ],'Server Statue', select=True, readonly=True),
108         'delete_queue_period': fields.integer('Delete after', help="delete emails/contents from email queue after specified no of days"),
109     }
110     
111     def _get_users(self, cr, uid, context={}):
112         return self.pool.get('res.users').search(cr, uid, [])
113     
114     _defaults = {
115         'date_create': lambda *a: time.strftime('%Y-%m-%d'),
116         'state': lambda *a: 'new',
117         'type': lambda *a: 'default',
118         'port': lambda *a: '25',
119         'pstate':lambda *a: 'stop',
120         'priority': lambda *a: 5,
121         'delete_queue_period': lambda *a: 30,
122         'auth': lambda *a: True,
123         'active': lambda *a: True,
124         'delete_queue': lambda *a: 'never',
125         'users_id': _get_users,
126         'verify_email': lambda *a: _("Verification Message. This is the code\n\n__code__\n\nyou must copy in the OpenERP Email Server (Verify Server wizard).\n\nCreated by user __user__"),
127     }
128     
129     server = {}
130     smtpServer = {}
131     
132     def create(self, cr, user, vals, context={}):
133         if vals.get('password', False) != False:
134             vals['password'] = base64.b64encode(vals.get('password'))
135             
136         res_id = super(smtpclient, self).create(cr, user, vals, context)
137         return res_id
138     
139     def write(self, cr, user, ids, vals, context=None):
140         flag = False
141         if vals.get('password', False) != False:
142             for pass_char in vals.get('password'):
143                 if pass_char != '*':
144                     flag= True
145                     break
146
147             if flag:    
148                 vals['password'] = base64.b64encode(vals.get('password'))
149             else:
150                 del vals['password']    
151             
152         res = super(smtpclient, self).write(cr, user, ids, vals, context)
153         return res
154     
155     def read(self,cr, uid, ids, fields=None, context=None, load='_classic_read'):
156         def override_password(o):
157             if len(o) > 0:
158                 for field in o[0]:
159                     if field == 'password':
160                         o[0][field] = '********'
161             return o
162
163         result = super(smtpclient, self).read(cr, uid, ids, fields, context, load)
164         result = override_password(result)
165         return result
166         
167     def change_servertype(self, cr, uid, ids, server):
168         if server == 'gmail':
169             return {'value':{'server':'smtp.gmail.com', 'port':'25', 'ssl':True, 'auth':True}}
170         elif server== 'yahoo':
171             return {'value':{'server':'smtp.mail.yahoo.co.in', 'ssl':False, 'port':'587', 'auth':True}}
172         else:
173             return {'value':{'server':'localhost', 'port':'25', 'ssl':False, 'auth':False}}
174     
175     def change_email(self, cr, uid, ids, email):
176         email_from = self.pool.get('res.users').browse(cr, uid, uid).name
177         if len(email) > 0 and email.find('@') > -1 and email.index('@') > 0:
178             user = email[0:email.index('@')]
179             return {'value':{'user':user, 'from_email':email_from+' <'+email+'>'}}
180         else:
181             return {'value':{'user':email, 'from_email':email_from+' <'+email+'>'}}
182
183     def check_permissions(self, cr, uid, ids):
184         if uid == 1:
185             return True
186         cr.execute('select * from res_smtpserver_group_rel where sid=%s and uid=%s' % (ids[0], uid))
187         data = cr.fetchall()
188         if len(data) <= 0:
189             return False
190
191         return True
192
193     def gen_private_key(self, cr, uid, ids):
194         new_key = []
195         for i in time.strftime('%Y-%m-%d %H:%M:%S'):
196             ky = i
197             if ky in (' ', '-', ':'):
198                 keys = random.random()
199                 key = str(keys).split('.')[1]
200                 ky = key
201
202             new_key.append(ky)
203         new_key.sort()
204         key = ''.join(new_key)
205         return key
206
207     
208     def _set_error(self, cr, uid, server_id, context={}):
209         server_obj = self.browse(cr, uid, server_id)
210         if not server_obj.active:
211             return 'not_active'
212         if server_obj.pstate == 'stop' :
213             return 'server_stop' 
214         if server_obj.state != 'confirm':
215             return 'server_not_confirm'
216         return True
217
218     def test_verify_email(self, cr, uid, ids, toemail, test=False, code=False):
219         
220         serverid = ids[0]
221         self.open_connection(cr, uid, ids, serverid)
222         
223         key = False
224         if test and self.server[serverid]['state'] == 'confirm':
225             body = self.server[serverid]['test_email'] or ''
226         else:
227             body = self.server[serverid]['verify_email'] or ''
228             #ignore the code
229             key = self.gen_private_key(cr, uid, ids)
230             #md5(time.strftime('%Y-%m-%d %H:%M:%S') + toemail).hexdigest();
231                 
232             body = body.replace("__code__", key)
233             
234         user = pooler.get_pool(cr.dbname).get('res.users').browse(cr, uid, [uid])[0]
235         body = body.replace("__user__", user.name)
236         
237         if len(body.strip()) <= 0:
238             raise osv.except_osv(_('Message Error!'), _('Please configure Email Server Messages [Verification / Test]'))
239         
240         try:
241             msg = MIMEText(body.encode('utf8') or '',_subtype='plain',_charset='utf-8')
242         except:
243             msg = MIMEText(body or '',_subtype='plain',_charset='utf-8')
244         
245         if not test and not self.server[serverid]['state'] == 'confirm':
246             msg['Subject'] = _('OpenERP SMTP server Email Registration Code!')
247         else:
248             msg['Subject'] = _('OpenERP Test Email!')
249         
250         msg['To'] = toemail
251         msg['From'] = tools.ustr(self.server[serverid]['from_email'])
252         
253         message = msg.as_string()
254         
255         if self.server[serverid]['disclaimers']:
256             body = body + "\n" + self.server[serverid]['disclaimers']
257             
258         queue = pooler.get_pool(cr.dbname).get('email.smtpclient.queue')
259         queue.create(cr, uid, {
260             'to':toemail,
261             'server_id':serverid,
262             'name':msg['Subject'],
263             'body':body,
264             'serialized_message':message,
265             'priority':1,
266             'type':'system'
267         })
268         
269         if self.server[serverid]['state'] != 'confirm':
270             self.write(cr, uid, ids, {'state':'waiting', 'code':key})
271             
272         return True
273          
274     def getpassword(self, cr, uid, ids):
275         data = {}
276         cr.execute("select * from email_smtpclient where id = %s" , (str(ids[0]),))
277         data = cr.dictfetchall()
278         return data
279
280     def open_connection(self, cr, uid, ids, serverid=False, permission=True):
281         if serverid:
282             self.server[serverid] = self.getpassword(cr, uid, [serverid])[0]
283         else:
284             raise osv.except_osv(_('Read Error!'), _('Unable to read Server Settings'))
285         
286         if permission:
287             if not self.check_permissions(cr, uid, [serverid]):
288                 raise osv.except_osv(_('Permission Error!'), _('You have no permission to access SMTP Server : %s ') % (self.server[serverid]['name'],) )
289         
290         if self.server[serverid]:
291             try:
292                 self.smtpServer[serverid] = smtplib.SMTP()
293                 self.smtpServer[serverid].debuglevel = 0
294                 self.smtpServer[serverid].connect(str(self.server[serverid]['server']),str(self.server[serverid]['port']))
295                 
296                 if self.server[serverid]['ssl']:
297                     self.smtpServer[serverid].ehlo()
298                     self.smtpServer[serverid].starttls()
299                     self.smtpServer[serverid].ehlo()
300                     
301                 if self.server[serverid]['auth']:
302                     password = self.server[serverid]['password']
303                     password = base64.b64decode(password)
304                     self.smtpServer[serverid].login(str(self.server[serverid]['user']), password)
305
306             except Exception, e:
307                 logger.notifyChannel('imap', netsvc.LOG_WARNING, e)
308             
309         return True
310     
311     def selectAddress(self, cr, uid, partner=None, contact=None, ):
312         email = 'none@none.com'
313         if partner is None and contact is None:
314             return 'none@none.com'
315          
316         if partner is not None and contact is None:
317             pool = self.pool.get('res.partner')
318             data = pool.read(cr, uid, [partner])[0]
319             if data:
320                 contact = data['address']
321
322         if contact is not None:
323             pool = self.pool.get('res.partner.address')
324             data = pool.read(cr, uid, contact)[0]
325             email = data['email']
326         
327         return email
328     
329     def select(self, cr, uid, type):
330         pool = self.pool.get('email.smtpclient')
331         ids = pool.search(cr, uid, [('type','=',type)], context=False)
332         if not ids:
333             ids = pool.search(cr, uid, [('type','=','default')], context=False)
334         
335         if not ids:
336             return False
337         
338         return ids[0]
339     
340     # Reports is a list of tuples,where first arguement of tuple is the name of the report,second is the list of ids of the object
341     def send_email(self, cr, uid, server_id, emailto, subject, body='', attachments=[], reports=[], ir_attach=[], charset='utf-8', headers={}, context={}):
342         
343         if not emailto:
344             raise osv.except_osv(_('SMTP Data Error !'), _('Email TO Address not Defined !'))
345         
346         def createReport(cr, uid, report, ids, name=False):
347             files = []
348             for id in ids:
349                 try:
350                     service = netsvc.LocalService(report)
351                     (result, format) = service.create(cr, uid, [id], {}, {})
352                     if not name:
353                         report_file = '/tmp/reports'+ str(id) + '.pdf'
354                     else:
355                         report_file = name
356                     
357                     fp = open(report_file,'wb+')
358                     fp.write(result);
359                     fp.close();
360                     files += [report_file]    
361                 except Exception,e:
362                     continue        
363             return files
364         
365         smtp_server = self.browse(cr, uid, server_id)
366         if smtp_server.state != 'confirm':
367             raise osv.except_osv(_('SMTP Server Error !'), _('Server is not Verified, Please Verify the Server !'))
368         
369         if not subject:
370             subject = "OpenERP Email: [Unknown Subject]"
371             
372         try:
373             subject = subject.encode(charset)
374         except:
375             subject = subject.decode()   
376
377         #attachment from Reports
378         for rpt in reports:
379             if len(rpt) == 3:
380                 rpt_file = createReport(cr, uid, rpt[0], rpt[1], rpt[2])
381             elif len(rpt) == 2:
382                 rpt_file = createReport(cr, uid, rpt[0], rpt[1])
383             attachments += rpt_file
384         
385         if isinstance(emailto, str) or isinstance(emailto, unicode):
386             emailto = [emailto]
387
388         ir_pool = self.pool.get('ir.attachment')
389         
390         for to in emailto:
391             msg = MIMEMultipart()
392             msg['Subject'] = tools.ustr(subject) 
393             msg['To'] =  to
394             msg['From'] = context.get('email_from', smtp_server.from_email)
395             
396             if body == False:
397                 body = ''
398                             
399             if smtp_server.disclaimers:
400                 body = body + "\n" + smtp_server.disclaimers
401                 
402             try:
403                 msg.attach(MIMEText(body.encode(charset) or '', _charset=charset, _subtype="html"))
404             except:
405                 msg.attach(MIMEText(body or '', _charset=charset, _subtype="html"))    
406             
407             #add custom headers to email
408             for hk in headers.keys():
409                 msg[hk] = headers[hk]
410
411             for hk in smtp_server.header_ids:
412                 msg[hk.key] = hk.value
413               
414             context_headers = context.get('headers', [])
415             for hk in context_headers:
416                 msg[hk] = context_headers[hk]
417             
418             # Add OpenERP Server information
419             msg['X-Generated-By'] = 'OpenERP (http://www.openerp.com)'
420             msg['X-OpenERP-Server-Host'] = socket.gethostname()
421             msg['X-OpenERP-Server-Version'] = release.version
422             msg['Message-Id'] = "<%s-openerp-@%s>" % (time.time(), socket.gethostname())
423           
424             #attach files from disc
425             for file in attachments:
426                 part = MIMEBase('application', "octet-stream")
427                 part.set_payload(open(file,"rb").read())
428                 Encoders.encode_base64(part)
429                 part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(file))
430                 msg.attach(part)
431             
432             #attach files from ir_attachments
433             for ath in ir_pool.browse(cr, uid, ir_attach):
434                 part = MIMEBase('application', "octet-stream")
435                 datas = base64.decodestring(ath.datas)
436                 part.set_payload(datas)
437                 Encoders.encode_base64(part)
438                 part.add_header('Content-Disposition', 'attachment; filename="%s"' %(ath.name))
439                 msg.attach(part)
440             
441             message = msg.as_string()
442             data = {
443                 'to':to,
444                 'server_id':server_id,
445                 'cc':False,
446                 'bcc':False,
447                 'name':subject,
448                 'body':body,
449                 'serialized_message':message,
450                 'priority':smtp_server.priority,
451             }
452             self.create_queue_enrty(cr, uid, data, context)
453             
454         return True
455     
456     def create_queue_enrty(self, cr, uid, data, context={}):
457         queue = pooler.get_pool(cr.dbname).get('email.smtpclient.queue')
458         return queue.create(cr, uid, data, context)
459         
460     def _check_history(self, cr, uid, ids=False, context={}):
461         result = True
462         server = self.pool.get('email.smtpclient')
463         queue = self.pool.get('email.smtpclient.queue')
464         sids = self.search(cr, uid, [])
465         for server in self.browse(cr, uid, sids):
466             if server.delete_queue == 'never':
467                 continue
468             
469             now = datetime.today()
470             days = timedelta(days=server.delete_queue_period)
471             day = now - days
472             kday = day.__str__().split(' ')[0]
473             
474             if server.delete_queue == 'content':
475                 qids = queue.search(cr, uid, [('server_id','=',server.id), ('date_create','<=',kday)])
476                 queue.write(cr, uid, qids, {'serialized_message':False})
477                 continue
478             
479             if server.delete_queue == 'all':
480                 qids = queue.search(cr, uid, [('server_id','=',server.id), ('date_create','<=',kday)])
481                 queue.unlink(cr, uid, qids)
482                 
483         return result
484     
485     def _send_emails(self, cr, uid, ids, context={}):
486         queue = self.pool.get('email.smtpclient.queue')
487         history = self.pool.get('email.smtpclient.history')
488         queue.write(cr, uid, ids, {'state':'sending'})
489         
490         error = []
491         sent = []
492         remove = []
493         open_server = []
494         
495         for email in queue.browse(cr, uid, ids):
496             
497             if not email.server_id.id in open_server:
498                 open_server.append(email.server_id.id)
499                 self.open_connection(cr, uid, ids, email.server_id.id)
500                 
501             try:
502                 self.smtpServer[email.server_id.id].sendmail(email.server_id.email, email.to, tools.ustr(email.serialized_message))
503                 message = "message sent successfully to %s from %s server" % (email.to, email.server_id.name)
504                 logger.notifyChannel('smtp', netsvc.LOG_INFO, message)
505             except Exception, e:
506                 queue.write(cr, uid, [email.id], {'error':e, 'state':'error'})
507                 continue
508             
509             history.create(cr, uid, {
510                 'name':email.body,
511                 'user_id':uid,
512                 'server_id': email.server_id.id,
513                 'email':email.to
514             })
515             if email.server_id.delete_queue == 'after_send':
516                 remove.append(email.id)
517             else:
518                 sent.append(email.id)
519         
520         queue.unlink(cr, uid, remove)
521         queue.write(cr, uid, sent, {'state':'send'})
522         return True
523     
524     def _check_queue(self, cr, uid, ids=False):
525         queue = self.pool.get('email.smtpclient.queue')
526         sids = []
527         if not ids:
528             sids = queue.search(cr, uid, [('state','not in',['send','sending']), ('type','=','system')], order="priority", limit=30)
529             ids =[]
530         else:
531             sids = queue.search(cr, uid, [('state','not in',['send','sending']), ('server_id','in',ids)], order="priority", limit=30)
532         
533         message = ""
534         if len(ids) > 0:
535             message = "sending %s emails from message queuq !" % (len(ids))
536             logger.notifyChannel('smtp', netsvc.LOG_INFO, message)
537         
538         result = self. _send_emails(cr, uid, sids, {})
539         return result
540         
541     def set_to_draft(self, cr, uid, ids, context={}):
542         self.write(cr, uid, ids, {'state':'new', 'code':False})
543         return True
544     
545     def create_process(self, cr, uid, ids, context={}):
546         svr = self.browse(cr, uid, ids[0])
547         if not svr.process_id:
548             res = {
549                 'name':'Process : ' + svr.name,
550                 'model':'email.smtpclient',
551                 'args': repr([ids]), 
552                 'function':'_check_queue',
553                 'priority':5,
554                 'interval_number':1,
555                 'interval_type':'minutes',
556                 'user_id':uid,
557                 'numbercall':-1,
558                 'doall':False
559             }
560             id = self.pool.get('ir.cron').create(cr, uid, res)
561             self.write(cr, uid, ids, {'process_id':id})
562         return True
563         
564     def start_process(self, cr, uid, ids, context={}):
565         process = self.browse(cr, uid, ids[0], context)
566         if not process.process_id:
567             raise osv.except_osv(_('SMTP Server Error !'), _('Server is not Verified, Please Verify the Server !'))
568             
569         pid = process.process_id.id
570         self.pool.get('ir.cron').write(cr, uid, [pid], {'active':True})
571         self.write(cr, uid, ids, {'pstate':'running'})
572         return True
573         
574     def stop_process(self, cr, uid, ids, context={}):
575         pid = self.browse(cr, uid, ids[0], context).process_id.id
576         self.pool.get('ir.cron').write(cr, uid, [pid], {'active':False})
577         self.write(cr, uid, ids, {'pstate':'stop'})
578         return True
579
580 smtpclient()
581
582 class email_headers(osv.osv):
583     _name = 'email.headers'
584     _description = 'Email Headers'
585     _columns = {
586         'server_id':fields.many2one('email.smtpclient', 'SMTP Server'),
587         'key':fields.char('Header', size=64, required=True),
588         'value':fields.char('Value', size=1024, required=False),
589     }
590 email_headers()
591
592 class email_history(osv.osv):
593     _name = 'email.smtpclient.history'
594     _description = 'Email Client History'
595     _order = 'id desc'
596
597     _columns = {
598         'name' : fields.text('Description',required=True, readonly=True),
599         'date_create': fields.datetime('Date',readonly=True),
600         'user_id':fields.many2one('res.users', 'Username', readonly=True, select=True),
601         'server_id' : fields.many2one('email.smtpclient', 'Smtp Server', ondelete='set null', readonly=True, required=True),
602         'model':fields.many2one('ir.model', 'Model', readonly=True, select=True),
603         'resource_id':fields.integer('Resource ID', readonly=True),
604         'email':fields.char('Email',size=64,readonly=True),
605     }
606     
607     _defaults = {
608         'date_create': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
609         'user_id': lambda obj, cr, uid, context: uid,
610     }
611     
612     def create(self, cr, uid, vals, context=None):
613         super(email_history,self).create(cr, uid, vals, context)
614         cr.commit()
615 email_history()
616
617 class message_queue(osv.osv):
618     _name = 'email.smtpclient.queue'
619     _description = 'Email Queue'
620     _order = '"to"'
621     _columns = {
622         'to' : fields.char('Mail to', size=1024, readonly=True, states={'draft':[('readonly',False)], 'error':[('readonly',False)]}),
623         'server_id':fields.many2one('email.smtpclient', 'SMTP Server', readonly=True, states={'draft':[('readonly',False)]}),
624         'cc' : fields.char('CC to', size=1024, readonly=True, states={'draft':[('readonly',False)]}),
625         'bcc' : fields.char('BCC to', size=1024, readonly=True, states={'draft':[('readonly',False)]}),
626         'name' : fields.char('Subject', size=1024, readonly=True, states={'draft':[('readonly',False)]}),
627         'body' : fields.text('Email Text', readonly=True, states={'draft':[('readonly',False)]}),
628         'serialized_message':fields.text('Message', readonly=True, states={'draft':[('readonly',False)]}),
629         'state':fields.selection([
630             ('draft','Queued'),
631             ('sending','Waiting'),
632             ('send','Sent'),
633             ('error','Error'),
634         ],'Message Status', select=True, readonly=True),
635         'type':fields.selection([
636             ('default','Default Message'),
637             ('system','System Message'),
638         ],'Message Type', select=True, readonly=True),
639         'error':fields.text('Last Error', size=256, readonly=True, states={'draft':[('readonly',False)]}),
640         'date_create': fields.datetime('Date', readonly=True),
641         'priority':fields.integer('Message Priority', readonly=True),
642     }
643     _defaults = {
644         'date_create': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
645         'state': lambda *a: 'draft',
646         'priority': lambda *a: '10',
647         'type': lambda *a: 'default',
648     }
649 message_queue()
650
651 class report_smtp_server(osv.osv):
652     _name = "report.smtp.server"
653     _description = "Server Statistics"
654     _auto = False
655     _columns = {
656         'server_id':fields.many2one('email.smtpclient','Server ID',readonly=True),
657         'name': fields.char('Server',size=64,readonly=True),
658         'history':fields.char('History',size=64, readonly=True),
659         'no':fields.integer('Total No.',readonly=True),
660     }
661     def init(self, cr):
662          cr.execute("""
663             create or replace view report_smtp_server as (
664                    select min(h.id) as id, c.id as server_id, h.name as history, h.name as name, count(h.name) as no  from email_smtpclient c inner join email_smtpclient_history h on c.id=h.server_id group by h.name, c.id
665                               )
666          """)
667          
668 report_smtp_server()
669
670 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
671