You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

225 lines
9.5 KiB

  1. # -*- encoding: utf-8 -*-
  2. ##############################################################################
  3. #
  4. # OpenERP, Open Source Management Solution
  5. # This module copyright (C) 2013 Therp BV (<http://therp.nl>)
  6. # All Rights Reserved
  7. #
  8. # This program is free software: you can redistribute it and/or modify
  9. # it under the terms of the GNU Affero General Public License as
  10. # published by the Free Software Foundation, either version 3 of the
  11. # License, or (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU Affero General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU Affero General Public License
  19. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. #
  21. ##############################################################################
  22. import simplejson
  23. from lxml import etree
  24. from openerp.osv.orm import Model, except_orm, browse_null
  25. from openerp.tools.translate import _
  26. from openerp.osv import fields
  27. from openerp.addons.fetchmail.fetchmail import logger
  28. from openerp.tools.misc import UnquoteEvalContext
  29. from openerp.tools.safe_eval import safe_eval
  30. class fetchmail_server(Model):
  31. _inherit = 'fetchmail.server'
  32. _columns = {
  33. 'folder_ids': fields.one2many(
  34. 'fetchmail.server.folder', 'server_id', 'Folders'),
  35. }
  36. _defaults = {
  37. 'type': 'imap',
  38. }
  39. def __init__(self, pool, cr):
  40. self._columns['object_id'].required=False
  41. return super(fetchmail_server, self).__init__(pool, cr)
  42. def onchange_server_type(
  43. self, cr, uid, ids, server_type=False, ssl=False,
  44. object_id=False):
  45. retval = super(
  46. fetchmail_server, self).onchange_server_type(cr, uid,
  47. ids, server_type, ssl, object_id)
  48. retval['value']['state']='draft'
  49. return retval
  50. def fetch_mail(self, cr, uid, ids, context=None):
  51. if context is None:
  52. context = {}
  53. check_original = []
  54. for this in self.browse(cr, uid, ids, context):
  55. if this.object_id:
  56. check_original.append(this.id)
  57. context.update(
  58. {
  59. 'fetchmail_server_id': this.id,
  60. 'server_type': this.type
  61. })
  62. connection = this.connect()
  63. for folder in this.folder_ids:
  64. logger.info('start checking for emails in %s server %s',
  65. folder.path, this.name)
  66. matcher = folder.get_algorithm()
  67. if connection.select(folder.path)[0] != 'OK':
  68. logger.error(
  69. 'Could not open mailbox %s on %s' % (
  70. folder.path, this.server))
  71. connection.select()
  72. continue
  73. result, msgids = connection.search(None, 'UNDELETED')
  74. if result != 'OK':
  75. logger.error(
  76. 'Could not search mailbox %s on %s' % (
  77. folder.path, this.server))
  78. continue
  79. for msgid in msgids[0].split():
  80. result, msgdata = connection.fetch(msgid, '(RFC822)')
  81. if result != 'OK':
  82. logger.error(
  83. 'Could not fetch %s in %s on %s' % (
  84. msgid, folder.path, this.server))
  85. continue
  86. mail_message = self.pool.get('mail.message').parse_message(
  87. msgdata[0][1], this.original)
  88. if self.pool.get('mail.message').search(cr, uid, [
  89. ('message_id','=',mail_message['message-id'])]):
  90. continue
  91. found_ids = matcher.search_matches(
  92. cr, uid, folder,
  93. mail_message, msgdata[0][1])
  94. if found_ids and (len(found_ids) == 1 or
  95. folder.match_first):
  96. try:
  97. matcher.handle_match(
  98. cr, uid, connection,
  99. found_ids[0], folder, mail_message,
  100. msgdata[0][1], msgid, context)
  101. cr.commit()
  102. except Exception, e:
  103. cr.rollback()
  104. logger.exception(
  105. "Failed to fetch mail %s from %s",
  106. msgid, this.name)
  107. elif folder.flag_nonmatching:
  108. connection.store(msgid, '+FLAGS', '\\FLAGGED')
  109. connection.close()
  110. return super(fetchmail_server, self).fetch_mail(
  111. cr, uid, check_original, context)
  112. def attach_mail(
  113. self, cr, uid, ids, connection, object_id, folder,
  114. mail_message, msgid, context=None):
  115. for this in self.browse(cr, uid, ids, context):
  116. partner_id = None
  117. if folder.model_id.model == 'res.partner':
  118. partner_id = object_id
  119. if self.pool.get(folder.model_id.model)._columns.\
  120. has_key('partner_id'):
  121. partner_id=self.pool.get(
  122. folder.model_id.model).browse(
  123. cr, uid, object_id, context
  124. ).partner_id.id
  125. self.pool.get('mail.message').create(
  126. cr, uid,
  127. {
  128. 'partner_id': partner_id,
  129. 'model': folder.model_id.model,
  130. 'res_id': object_id,
  131. 'body_text': mail_message.get('body'),
  132. 'body_html': mail_message.get('body_html'),
  133. 'subject': mail_message.get('subject'),
  134. 'email_to': mail_message.get('to'),
  135. 'email_from': mail_message.get('from'),
  136. 'email_cc': mail_message.get('cc'),
  137. 'reply_to': mail_message.get('reply'),
  138. 'date': mail_message.get('date'),
  139. 'message_id': mail_message.get('message-id'),
  140. 'subtype': mail_message.get('subtype'),
  141. 'headers': mail_message.get('headers'),
  142. },
  143. context)
  144. if this.attach:
  145. #TODO: create attachments
  146. pass
  147. if folder.delete_matching:
  148. connection.store(msgid, '+FLAGS', '\\DELETED')
  149. def button_confirm_login(self, cr, uid, ids, context=None):
  150. retval = super(fetchmail_server, self).button_confirm_login(cr, uid,
  151. ids, context)
  152. for this in self.browse(cr, uid, ids, context):
  153. this.write({'state': 'draft'})
  154. connection = this.connect()
  155. connection.select()
  156. for folder in this.folder_ids:
  157. if connection.select(folder.path)[0] != 'OK':
  158. raise except_orm(
  159. _('Error'), _('Mailbox %s not found!') %
  160. folder.path)
  161. folder.get_algorithm().search_matches(
  162. cr, uid, folder, browse_null(), '')
  163. connection.close()
  164. this.write({'state': 'done'})
  165. return retval
  166. def fields_view_get(self, cr, user, view_id=None, view_type='form',
  167. context=None, toolbar=False, submenu=False):
  168. result = super(fetchmail_server, self).fields_view_get(
  169. cr, user, view_id, view_type, context, toolbar, submenu)
  170. if view_type == 'form':
  171. view = etree.fromstring(
  172. result['fields']['folder_ids']['views']['form']['arch'])
  173. modifiers={}
  174. docstr=''
  175. for algorithm in self.pool.get('fetchmail.server.folder')\
  176. ._get_match_algorithms().itervalues():
  177. for modifier in ['required', 'readonly']:
  178. for field in getattr(algorithm, modifier + '_fields'):
  179. modifiers.setdefault(field, {})
  180. modifiers[field].setdefault(modifier, [])
  181. if modifiers[field][modifier]:
  182. modifiers[field][modifier].insert(0, '|')
  183. modifiers[field][modifier].append(
  184. ("match_algorithm","==",algorithm.__name__))
  185. docstr += _(algorithm.name) + '\n' + _(algorithm.__doc__) + \
  186. '\n\n'
  187. for field in view:
  188. if field.tag == 'field' and field.get('name') in modifiers:
  189. field.set('modifiers', simplejson.dumps(
  190. dict(
  191. eval(field.attrib['modifiers'],
  192. UnquoteEvalContext({})),
  193. **modifiers[field.attrib['name']])))
  194. if (field.tag == 'field' and
  195. field.get('name') == 'match_algorithm'):
  196. field.set('help', docstr)
  197. result['fields']['folder_ids']['views']['form']['arch'] = \
  198. etree.tostring(view)
  199. return result