|
@ -22,13 +22,10 @@ |
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
|
############################################################################## |
|
|
############################################################################## |
|
|
from openerp.osv import fields, orm |
|
|
from openerp.osv import fields, orm |
|
|
from openerp.tools import ( |
|
|
|
|
|
DEFAULT_SERVER_DATETIME_FORMAT as DSDTF) |
|
|
|
|
|
import logging |
|
|
import logging |
|
|
import imaplib |
|
|
import imaplib |
|
|
from datetime import datetime |
|
|
from datetime import datetime |
|
|
import time |
|
|
import time |
|
|
import calendar |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_logger = logging.getLogger(__name__) |
|
|
_logger = logging.getLogger(__name__) |
|
@ -51,14 +48,12 @@ class FetchmailServer(orm.Model): |
|
|
date_uids = {} |
|
|
date_uids = {} |
|
|
last_date = False |
|
|
last_date = False |
|
|
last_internal_date = datetime.strptime( |
|
|
last_internal_date = datetime.strptime( |
|
|
server.last_internal_date, DSDTF) |
|
|
|
|
|
timestamp1 = calendar.timegm( |
|
|
|
|
|
last_internal_date.timetuple()) |
|
|
|
|
|
intDate = imaplib.Time2Internaldate(timestamp1) |
|
|
|
|
|
|
|
|
server.last_internal_date, "%Y-%m-%d %H:%M:%S") |
|
|
|
|
|
#~ timestamp1 = time.mktime(last_internal_date.timetuple()) |
|
|
|
|
|
#~ intDate = imaplib.Time2Internaldate(timestamp1) |
|
|
search_status, uids = imap_server.search( |
|
|
search_status, uids = imap_server.search( |
|
|
None, |
|
|
None, |
|
|
'SINCE', |
|
|
|
|
|
'%s' % intDate |
|
|
|
|
|
|
|
|
'SINCE', '%s' % last_internal_date.strftime('%d-%b-%Y') |
|
|
) |
|
|
) |
|
|
new_uids = uids[0].split() |
|
|
new_uids = uids[0].split() |
|
|
for new_uid in new_uids: |
|
|
for new_uid in new_uids: |
|
@ -77,9 +72,9 @@ class FetchmailServer(orm.Model): |
|
|
# SEARCH command *always* returns at least the most |
|
|
# SEARCH command *always* returns at least the most |
|
|
# recent message, even if it has already been synced |
|
|
# recent message, even if it has already been synced |
|
|
res_id = None |
|
|
res_id = None |
|
|
result, data = imap_server.uid('fetch', num, |
|
|
|
|
|
'(RFC822)') |
|
|
|
|
|
|
|
|
result, data = imap_server.fetch(num, '(RFC822)') |
|
|
imap_server.store(num, '-FLAGS', '\\Seen') |
|
|
imap_server.store(num, '-FLAGS', '\\Seen') |
|
|
|
|
|
if data and data[0]: |
|
|
try: |
|
|
try: |
|
|
res_id = mail_thread.message_process( |
|
|
res_id = mail_thread.message_process( |
|
|
cr, uid, |
|
|
cr, uid, |
|
@ -96,111 +91,21 @@ class FetchmailServer(orm.Model): |
|
|
server.name) |
|
|
server.name) |
|
|
failed += 1 |
|
|
failed += 1 |
|
|
if res_id and server.action_id: |
|
|
if res_id and server.action_id: |
|
|
action_pool.run(cr, uid, [server.action_id.id], |
|
|
|
|
|
{'active_id': res_id, |
|
|
|
|
|
|
|
|
action_pool.run( |
|
|
|
|
|
cr, uid, [server.action_id.id], |
|
|
|
|
|
{ |
|
|
|
|
|
'active_id': res_id, |
|
|
'active_ids': [res_id], |
|
|
'active_ids': [res_id], |
|
|
'active_model': context.get( |
|
|
'active_model': context.get( |
|
|
"thread_model", |
|
|
"thread_model", |
|
|
server.object_id.model)} |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
server.object_id.model) |
|
|
|
|
|
}, context=context) |
|
|
imap_server.store(num, '+FLAGS', '\\Seen') |
|
|
imap_server.store(num, '+FLAGS', '\\Seen') |
|
|
cr.commit() |
|
|
cr.commit() |
|
|
count += 1 |
|
|
count += 1 |
|
|
last_date = not failed and date_uids[num] or False |
|
|
last_date = not failed and date_uids[num] or False |
|
|
return count, failed, last_date |
|
|
return count, failed, last_date |
|
|
|
|
|
|
|
|
def _fetch_unread_imap(self, cr, uid, |
|
|
|
|
|
server, imap_server, |
|
|
|
|
|
mail_thread, action_pool, |
|
|
|
|
|
count, failed, |
|
|
|
|
|
context=None): |
|
|
|
|
|
result, data = imap_server.search(None, '(UNSEEN)') |
|
|
|
|
|
for num in data[0].split(): |
|
|
|
|
|
res_id = None |
|
|
|
|
|
result, data = imap_server.fetch(num, '(RFC822)') |
|
|
|
|
|
imap_server.store(num, '-FLAGS', '\\Seen') |
|
|
|
|
|
try: |
|
|
|
|
|
res_id = mail_thread.message_process( |
|
|
|
|
|
cr, uid, server.object_id.model, |
|
|
|
|
|
data[0][1], |
|
|
|
|
|
save_original=server.original, |
|
|
|
|
|
strip_attachments=(not server.attach), |
|
|
|
|
|
context=context) |
|
|
|
|
|
except Exception: |
|
|
|
|
|
_logger.exception( |
|
|
|
|
|
'Failed to process mail \ |
|
|
|
|
|
from %s server %s.', |
|
|
|
|
|
server.type, |
|
|
|
|
|
server.name) |
|
|
|
|
|
failed += 1 |
|
|
|
|
|
if res_id and server.action_id: |
|
|
|
|
|
action_pool.run(cr, uid, |
|
|
|
|
|
[server.action_id.id], |
|
|
|
|
|
{'active_id': res_id, |
|
|
|
|
|
'active_ids': [res_id], |
|
|
|
|
|
'active_model': context.get( |
|
|
|
|
|
"thread_model", |
|
|
|
|
|
server.object_id.model)} |
|
|
|
|
|
) |
|
|
|
|
|
imap_server.store(num, '+FLAGS', '\\Seen') |
|
|
|
|
|
cr.commit() |
|
|
|
|
|
count += 1 |
|
|
|
|
|
return count, failed |
|
|
|
|
|
|
|
|
|
|
|
def _fetch_unread_pop(self, cr, uid, |
|
|
|
|
|
server, mail_thread, |
|
|
|
|
|
failed, action_pool, |
|
|
|
|
|
context=None): |
|
|
|
|
|
try: |
|
|
|
|
|
pop_server = server.connect() |
|
|
|
|
|
(numMsgs, totalSize) = pop_server.stat() |
|
|
|
|
|
pop_server.list() |
|
|
|
|
|
for num in range(1, numMsgs + 1): |
|
|
|
|
|
(header, msges, octets) = pop_server.retr(num) |
|
|
|
|
|
msg = '\n'.join(msges) |
|
|
|
|
|
res_id = None |
|
|
|
|
|
try: |
|
|
|
|
|
res_id = mail_thread.message_process( |
|
|
|
|
|
cr, uid, server.object_id.model, |
|
|
|
|
|
msg, |
|
|
|
|
|
save_original=server.original, |
|
|
|
|
|
strip_attachments=(not server.attach), |
|
|
|
|
|
context=context) |
|
|
|
|
|
except Exception: |
|
|
|
|
|
_logger.exception( |
|
|
|
|
|
'Failed to process mail \ |
|
|
|
|
|
from %s server %s.', |
|
|
|
|
|
server.type, |
|
|
|
|
|
server.name) |
|
|
|
|
|
failed += 1 |
|
|
|
|
|
if res_id and server.action_id: |
|
|
|
|
|
action_pool.run(cr, uid, [server.action_id.id], |
|
|
|
|
|
{'active_id': res_id, |
|
|
|
|
|
'active_ids': [res_id], |
|
|
|
|
|
'active_model': context.get( |
|
|
|
|
|
"thread_model", |
|
|
|
|
|
server.object_id.model)} |
|
|
|
|
|
) |
|
|
|
|
|
pop_server.dele(num) |
|
|
|
|
|
cr.commit() |
|
|
|
|
|
_logger.info( |
|
|
|
|
|
"Fetched %d email(s) on %s server %s; \ |
|
|
|
|
|
%d succeeded, %d failed.", |
|
|
|
|
|
numMsgs, |
|
|
|
|
|
server.type, |
|
|
|
|
|
server.name, |
|
|
|
|
|
(numMsgs - failed), |
|
|
|
|
|
failed) |
|
|
|
|
|
except Exception: |
|
|
|
|
|
_logger.exception( |
|
|
|
|
|
"General failure when trying to fetch \ |
|
|
|
|
|
mail from %s server %s.", |
|
|
|
|
|
server.type, |
|
|
|
|
|
server.name) |
|
|
|
|
|
finally: |
|
|
|
|
|
if pop_server: |
|
|
|
|
|
pop_server.quit() |
|
|
|
|
|
|
|
|
|
|
|
def fetch_mail(self, cr, uid, ids, context=None): |
|
|
def fetch_mail(self, cr, uid, ids, context=None): |
|
|
"""WARNING: meant for cron usage only - |
|
|
"""WARNING: meant for cron usage only - |
|
|
will commit() after each email! |
|
|
will commit() after each email! |
|
@ -211,7 +116,8 @@ class FetchmailServer(orm.Model): |
|
|
mail_thread = self.pool.get('mail.thread') |
|
|
mail_thread = self.pool.get('mail.thread') |
|
|
action_pool = self.pool.get('ir.actions.server') |
|
|
action_pool = self.pool.get('ir.actions.server') |
|
|
for server in self.browse(cr, uid, ids, context=context): |
|
|
for server in self.browse(cr, uid, ids, context=context): |
|
|
_logger.info('start checking for new emails on %s server %s', |
|
|
|
|
|
|
|
|
_logger.info( |
|
|
|
|
|
'start checking for new emails by date on %s server %s', |
|
|
server.type, server.name) |
|
|
server.type, server.name) |
|
|
context.update({'fetchmail_server_id': server.id, |
|
|
context.update({'fetchmail_server_id': server.id, |
|
|
'server_type': server.type}) |
|
|
'server_type': server.type}) |
|
@ -224,33 +130,9 @@ class FetchmailServer(orm.Model): |
|
|
imap_server.select() |
|
|
imap_server.select() |
|
|
if server.last_internal_date: |
|
|
if server.last_internal_date: |
|
|
count, failed, last_date = self._fetch_from_data_imap( |
|
|
count, failed, last_date = self._fetch_from_data_imap( |
|
|
cr, |
|
|
|
|
|
uid, |
|
|
|
|
|
server, |
|
|
|
|
|
imap_server, |
|
|
|
|
|
mail_thread, |
|
|
|
|
|
action_pool, |
|
|
|
|
|
count, |
|
|
|
|
|
failed, |
|
|
|
|
|
context=context) |
|
|
|
|
|
count, failed = self._fetch_unread_imap( |
|
|
|
|
|
cr, |
|
|
|
|
|
uid, |
|
|
|
|
|
server, |
|
|
|
|
|
imap_server, |
|
|
|
|
|
mail_thread, |
|
|
|
|
|
action_pool, |
|
|
|
|
|
count, |
|
|
|
|
|
failed, |
|
|
|
|
|
context=context) |
|
|
|
|
|
_logger.info( |
|
|
|
|
|
"Fetched %d email(s) on %s server %s; \ |
|
|
|
|
|
%d succeeded, %d failed.", |
|
|
|
|
|
count, |
|
|
|
|
|
server.type, |
|
|
|
|
|
server.name, |
|
|
|
|
|
(count - failed), |
|
|
|
|
|
failed) |
|
|
|
|
|
|
|
|
cr, uid, server, imap_server, mail_thread, |
|
|
|
|
|
action_pool, count, failed, context=context |
|
|
|
|
|
) |
|
|
except Exception: |
|
|
except Exception: |
|
|
_logger.exception( |
|
|
_logger.exception( |
|
|
"General failure when trying to fetch mail \ |
|
|
"General failure when trying to fetch mail \ |
|
@ -262,15 +144,8 @@ class FetchmailServer(orm.Model): |
|
|
if imap_server: |
|
|
if imap_server: |
|
|
imap_server.close() |
|
|
imap_server.close() |
|
|
imap_server.logout() |
|
|
imap_server.logout() |
|
|
elif server.type == 'pop': |
|
|
|
|
|
self._fetch_unread_pop(cr, uid, |
|
|
|
|
|
server, mail_thread, |
|
|
|
|
|
failed, action_pool, |
|
|
|
|
|
context=context) |
|
|
|
|
|
vals = {'date': |
|
|
|
|
|
time.strftime(DSDTF) |
|
|
|
|
|
} |
|
|
|
|
|
if last_date: |
|
|
if last_date: |
|
|
vals['last_internal_date'] = last_date |
|
|
|
|
|
|
|
|
vals = {'last_internal_date': last_date} |
|
|
server.write(vals) |
|
|
server.write(vals) |
|
|
return True |
|
|
|
|
|
|
|
|
return super(FetchmailServer, self).fetch_mail( |
|
|
|
|
|
cr, uid, ids, context=context) |