2010-06-05 06:38:44 +00:00
# -*- coding: utf-8 -*-
2010-04-15 15:43:28 +00:00
##############################################################################
#
2010-06-05 06:38:44 +00:00
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
2010-04-15 15:43:28 +00:00
#
# This program is free software: you can redistribute it and/or modify
2010-06-05 06:38:44 +00:00
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
2010-04-15 15:43:28 +00:00
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2010-06-05 06:38:44 +00:00
# GNU Affero General Public License for more details.
2010-04-15 15:43:28 +00:00
#
2010-06-05 06:38:44 +00:00
# You should have received a copy of the GNU Affero General Public License
2010-04-15 15:43:28 +00:00
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import time
from imaplib import IMAP4
2010-06-24 19:53:32 +00:00
from imaplib import IMAP4_SSL
2010-04-19 20:57:36 +00:00
from poplib import POP3
from poplib import POP3_SSL
2010-04-15 15:43:28 +00:00
import netsvc
2010-06-24 19:53:32 +00:00
from osv import osv , fields
2010-04-15 15:43:28 +00:00
logger = netsvc . Logger ( )
2010-06-24 19:53:32 +00:00
2010-04-22 13:44:47 +00:00
class email_server ( osv . osv ) :
2010-06-24 19:53:32 +00:00
2010-04-15 15:43:28 +00:00
_name = ' email.server '
_description = " POP/IMAP Server "
2010-06-24 19:53:32 +00:00
2010-04-15 15:43:28 +00:00
_columns = {
2010-08-19 11:51:57 +00:00
' name ' : fields . char ( ' Name ' , size = 256 , required = True , readonly = False ) ,
' active ' : fields . boolean ( ' Active ' , required = False ) ,
2010-04-15 15:43:28 +00:00
' state ' : fields . selection ( [
2010-08-19 11:51:57 +00:00
( ' draft ' , ' Not Confirmed ' ) ,
2010-11-04 11:19:28 +00:00
( ' waiting ' , ' Waiting for Verification ' ) ,
2010-08-19 11:51:57 +00:00
( ' done ' , ' Confirmed ' ) ,
] , ' State ' , select = True , readonly = True ) ,
' server ' : fields . char ( ' Server ' , size = 256 , required = True , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
' port ' : fields . integer ( ' Port ' , required = True , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
2010-04-15 15:43:28 +00:00
' type ' : fields . selection ( [
2010-08-19 11:51:57 +00:00
( ' pop ' , ' POP Server ' ) ,
( ' imap ' , ' IMAP Server ' ) ,
] , ' Server Type ' , select = True , readonly = False ) ,
' is_ssl ' : fields . boolean ( ' SSL ? ' , required = False ) ,
2010-11-03 09:50:29 +00:00
' attach ' : fields . boolean ( ' Add Attachments ? ' , required = False , help = " Fetches mail with attachments if true. " ) ,
2010-08-19 11:51:57 +00:00
' date ' : fields . date ( ' Date ' , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
' user ' : fields . char ( ' User Name ' , size = 256 , required = True , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
' password ' : fields . char ( ' Password ' , size = 1024 , invisible = True , required = True , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } ) ,
' note ' : fields . text ( ' Description ' ) ,
2010-11-03 08:02:01 +00:00
' action_id ' : fields . many2one ( ' ir.actions.server ' , ' Reply Email ' , required = False , domain = " [( ' state ' , ' = ' , ' email ' )] " ,
2010-11-04 13:21:37 +00:00
help = " An Email Server Action. It will be run whenever an e-mail is fetched from server. " ) ,
2010-11-03 09:50:29 +00:00
' object_id ' : fields . many2one ( ' ir.model ' , " Model " , required = True , help = " OpenObject Model. Generates a record of this model. " ) ,
2010-08-19 11:51:57 +00:00
' priority ' : fields . integer ( ' Server Priority ' , readonly = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } , help = " Priority between 0 to 10, select define the order of Processing " ) ,
' user_id ' : fields . many2one ( ' res.users ' , ' User ' , required = False ) ,
2010-11-04 13:21:37 +00:00
' message_ids ' : fields . one2many ( ' mailgate.message ' , ' server_id ' , ' Messages ' , readonly = True ) ,
2010-04-15 15:43:28 +00:00
}
_defaults = {
2010-08-19 11:51:57 +00:00
' state ' : lambda * a : " draft " ,
' active ' : lambda * a : True ,
' priority ' : lambda * a : 5 ,
' date ' : lambda * a : time . strftime ( ' % Y- % m- %d ' ) ,
' user_id ' : lambda self , cr , uid , ctx : uid ,
2010-04-15 15:43:28 +00:00
}
2010-06-24 19:53:32 +00:00
2010-04-15 15:43:28 +00:00
def check_duplicate ( self , cr , uid , ids ) :
2010-10-17 17:30:00 +00:00
# RFC *-* Why this limitation? why not in SQL constraint?
2010-04-15 15:43:28 +00:00
vals = self . read ( cr , uid , ids , [ ' user ' , ' password ' ] ) [ 0 ]
2010-10-19 10:18:33 +00:00
cr . execute ( " select count(id) from email_server where user= %s and password= %s " , ( vals [ ' user ' ] , vals [ ' password ' ] ) )
2010-04-15 15:43:28 +00:00
res = cr . fetchone ( )
if res :
if res [ 0 ] > 1 :
return False
2010-06-24 19:53:32 +00:00
return True
2010-04-15 15:43:28 +00:00
_constraints = [
( check_duplicate , ' Warning! Can \' t have duplicate server configuration! ' , [ ' user ' , ' password ' ] )
]
2010-06-24 19:53:32 +00:00
2010-04-15 15:43:28 +00:00
def onchange_server_type ( self , cr , uid , ids , server_type = False , ssl = False ) :
port = 0
if server_type == ' pop ' :
port = ssl and 995 or 110
elif server_type == ' imap ' :
port = ssl and 993 or 143
2010-06-24 19:53:32 +00:00
2010-04-15 15:43:28 +00:00
return { ' value ' : { ' port ' : port } }
2010-04-27 14:44:13 +00:00
def set_draft ( self , cr , uid , ids , context = { } ) :
self . write ( cr , uid , ids , { ' state ' : ' draft ' } )
return True
2010-11-04 11:19:28 +00:00
def button_confirm_login ( self , cr , uid , ids , context = { } ) :
2010-04-15 15:43:28 +00:00
for server in self . browse ( cr , uid , ids , context ) :
logger . notifyChannel ( ' imap ' , netsvc . LOG_INFO , ' fetchmail start checking for new emails on %s ' % ( server . name ) )
2010-06-25 09:57:41 +00:00
context . update ( { ' server_id ' : server . id , ' server_type ' : server . type } )
2010-04-22 12:47:54 +00:00
count = 0
2010-04-22 13:44:47 +00:00
try :
if server . type == ' imap ' :
imap_server = None
if server . is_ssl :
imap_server = IMAP4_SSL ( server . server , int ( server . port ) )
else :
imap_server = IMAP4 ( server . server , int ( server . port ) )
2010-06-24 19:53:32 +00:00
2010-04-22 13:44:47 +00:00
imap_server . login ( server . user , server . password )
2010-11-04 11:19:28 +00:00
ret_server = imap_server
elif server . type == ' pop ' :
pop_server = None
if server . is_ssl :
pop_server = POP3_SSL ( server . server , int ( server . port ) )
else :
pop_server = POP3 ( server . server , int ( server . port ) )
#TODO: use this to remove only unread messages
#pop_server.user("recent:"+server.user)
pop_server . user ( server . user )
pop_server . pass_ ( server . password )
ret_server = pop_server
self . write ( cr , uid , [ server . id ] , { ' state ' : ' done ' } )
if context . get ( ' get_server ' , False ) :
return ret_server
except Exception , e :
logger . notifyChannel ( server . type , netsvc . LOG_WARNING , ' %s ' % ( e ) )
return True
def button_fetch_mail ( self , cr , uid , ids , context = { } ) :
self . fetch_mail ( cr , uid , ids , context = context )
return True
def _fetch_mails ( self , cr , uid , ids = False , context = { } ) :
if not ids :
ids = self . search ( cr , uid , [ ] )
return self . fetch_mail ( cr , uid , ids , context = context )
def fetch_mail ( self , cr , uid , ids , context = { } ) :
email_tool = self . pool . get ( ' email.server.tools ' )
action_pool = self . pool . get ( ' ir.actions.server ' )
context . update ( { ' get_server ' : True } )
for server in self . browse ( cr , uid , ids , context ) :
count = 0
try :
if server . type == ' imap ' :
imap_server = self . button_confirm_login ( cr , uid , [ server . id ] , context = context )
2010-04-22 13:44:47 +00:00
imap_server . select ( )
2010-08-19 11:51:57 +00:00
result , data = imap_server . search ( None , ' (UNSEEN) ' )
2010-04-22 13:44:47 +00:00
for num in data [ 0 ] . split ( ) :
result , data = imap_server . fetch ( num , ' (RFC822) ' )
2010-06-25 09:57:41 +00:00
res_id = email_tool . process_email ( cr , uid , server . object_id . model , data [ 0 ] [ 1 ] , attach = server . attach , context = context )
2010-06-24 19:53:32 +00:00
if res_id and server . action_id :
action_pool . run ( cr , uid , [ server . action_id . id ] , { ' active_id ' : res_id , ' active_ids ' : [ res_id ] } )
2010-04-22 13:44:47 +00:00
imap_server . store ( num , ' +FLAGS ' , ' \\ Seen ' )
2010-06-24 19:53:32 +00:00
count + = 1
2010-04-22 13:44:47 +00:00
logger . notifyChannel ( ' imap ' , netsvc . LOG_INFO , ' fetchmail fetch/process %s email(s) from %s ' % ( count , server . name ) )
2010-06-24 19:53:32 +00:00
2010-04-22 13:44:47 +00:00
imap_server . close ( )
imap_server . logout ( )
elif server . type == ' pop ' :
2010-11-04 11:19:28 +00:00
pop_server = self . button_confirm_login ( cr , uid , [ server . id ] , context = context )
2010-04-22 13:44:47 +00:00
pop_server . list ( )
( numMsgs , totalSize ) = pop_server . stat ( )
for num in range ( 1 , numMsgs + 1 ) :
( header , msges , octets ) = pop_server . retr ( num )
msg = ' \n ' . join ( msges )
2010-09-21 07:32:53 +00:00
res_id = email_tool . process_email ( cr , uid , server . object_id . model , msg , attach = server . attach , context = context )
2010-06-24 19:53:32 +00:00
if res_id and server . action_id :
action_pool . run ( cr , uid , [ server . action_id . id ] , { ' active_id ' : res_id , ' active_ids ' : [ res_id ] } )
2010-04-22 13:44:47 +00:00
pop_server . dele ( num )
2010-04-22 12:47:54 +00:00
2010-04-22 13:44:47 +00:00
pop_server . quit ( )
2010-06-24 19:53:32 +00:00
2010-04-22 13:44:47 +00:00
logger . notifyChannel ( ' imap ' , netsvc . LOG_INFO , ' fetchmail fetch %s email(s) from %s ' % ( numMsgs , server . name ) )
2010-06-24 19:53:32 +00:00
2010-04-22 13:44:47 +00:00
except Exception , e :
2010-04-26 05:20:01 +00:00
logger . notifyChannel ( server . type , netsvc . LOG_WARNING , ' %s ' % ( e ) )
2010-06-24 19:53:32 +00:00
2010-04-15 15:43:28 +00:00
return True
2010-04-19 20:57:36 +00:00
2010-04-22 13:44:47 +00:00
email_server ( )
2010-04-15 15:43:28 +00:00
2010-06-24 19:53:32 +00:00
class mailgate_message ( osv . osv ) :
_inherit = " mailgate.message "
2010-04-15 15:43:28 +00:00
_columns = {
2010-08-19 11:51:57 +00:00
' server_id ' : fields . many2one ( ' email.server ' , " Mail Server " , readonly = True , select = True ) ,
2010-09-16 13:06:07 +00:00
' server_type ' : fields . selection ( [
2010-08-19 11:51:57 +00:00
( ' pop ' , ' POP Server ' ) ,
( ' imap ' , ' IMAP Server ' ) ,
] , ' Server Type ' , select = True , readonly = True ) ,
2010-04-15 15:43:28 +00:00
}
_order = ' id desc '
2010-06-24 19:53:32 +00:00
2010-06-25 09:57:41 +00:00
def create ( self , cr , uid , values , context = None ) :
if not context :
context = { }
server_id = context . get ( ' server_id ' , False )
server_type = context . get ( ' server_type ' , False )
if server_id :
values [ ' server_id ' ] = server_id
if server_type :
values [ ' server_type ' ] = server_type
res = super ( mailgate_message , self ) . create ( cr , uid , values , context = context )
return res
def write ( self , cr , uid , ids , values , context = None ) :
if not context :
context = { }
server_id = context . get ( ' server_id ' , False )
server_type = context . get ( ' server_type ' , False )
if server_id :
values [ ' server_id ' ] = server_id
if server_type :
values [ ' server_type ' ] = server_type
res = super ( mailgate_message , self ) . write ( cr , uid , ids , values , context = context )
return res
2010-06-24 19:53:32 +00:00
mailgate_message ( )
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: