[REN] preliminary migration of fetchmail_attach_from_folder
parent
30bc88d900
commit
862d5a6bb8
|
@ -1,131 +0,0 @@
|
||||||
# -*- encoding: utf-8 -*-
|
|
||||||
##############################################################################
|
|
||||||
#
|
|
||||||
# OpenERP, Open Source Management Solution
|
|
||||||
# This module copyright (C) 2013 Therp BV (<http://therp.nl>)
|
|
||||||
# All Rights Reserved
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
# 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
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
########################################################################
|
|
||||||
|
|
||||||
from openerp.osv import fields
|
|
||||||
from openerp.osv.orm import Model
|
|
||||||
from .. import match_algorithm
|
|
||||||
|
|
||||||
|
|
||||||
class fetchmail_server_folder(Model):
|
|
||||||
_name = 'fetchmail.server.folder'
|
|
||||||
_rec_name = 'path'
|
|
||||||
|
|
||||||
def _get_match_algorithms(self):
|
|
||||||
def get_all_subclasses(cls):
|
|
||||||
return cls.__subclasses__() + [subsub
|
|
||||||
for sub in cls.__subclasses__()
|
|
||||||
for subsub in get_all_subclasses(sub)]
|
|
||||||
return dict([(cls.__name__, cls) for cls in get_all_subclasses(
|
|
||||||
match_algorithm.base.base)])
|
|
||||||
|
|
||||||
def _get_match_algorithms_sel(self, cr, uid, context=None):
|
|
||||||
algorithms = []
|
|
||||||
for cls in self._get_match_algorithms().itervalues():
|
|
||||||
algorithms.append((cls.__name__, cls.name))
|
|
||||||
algorithms.sort()
|
|
||||||
return algorithms
|
|
||||||
|
|
||||||
_columns = {
|
|
||||||
'sequence': fields.integer('Sequence'),
|
|
||||||
'path': fields.char(
|
|
||||||
'Path', size=256, help='The path to your mail '
|
|
||||||
"folder. Typically would be something like 'INBOX.myfolder'",
|
|
||||||
required=True
|
|
||||||
),
|
|
||||||
'model_id': fields.many2one(
|
|
||||||
'ir.model', 'Model', required=True,
|
|
||||||
help='The model to attach emails to'
|
|
||||||
),
|
|
||||||
'model_field': fields.char(
|
|
||||||
'Field (model)', size=128,
|
|
||||||
help='The field in your model that contains the field to match '
|
|
||||||
'against.\n'
|
|
||||||
'Examples:\n'
|
|
||||||
"'email' if your model is res.partner, or "
|
|
||||||
"'partner_id.email' if you're matching sale orders"
|
|
||||||
),
|
|
||||||
'model_order': fields.char(
|
|
||||||
'Order (model)', size=128,
|
|
||||||
help='Fields to order by, this mostly useful in conjunction '
|
|
||||||
"with 'Use 1st match'"
|
|
||||||
),
|
|
||||||
'match_algorithm': fields.selection(
|
|
||||||
_get_match_algorithms_sel,
|
|
||||||
'Match algorithm', required=True, translate=True,
|
|
||||||
help='The algorithm used to determine which object an email '
|
|
||||||
'matches.'
|
|
||||||
),
|
|
||||||
'mail_field': fields.char(
|
|
||||||
'Field (email)', size=128,
|
|
||||||
help='The field in the email used for matching. Typically '
|
|
||||||
"this is 'to' or 'from'"
|
|
||||||
),
|
|
||||||
'server_id': fields.many2one('fetchmail.server', 'Server'),
|
|
||||||
'delete_matching': fields.boolean(
|
|
||||||
'Delete matches',
|
|
||||||
help='Delete matched emails from server'
|
|
||||||
),
|
|
||||||
'flag_nonmatching': fields.boolean(
|
|
||||||
'Flag nonmatching',
|
|
||||||
help="Flag emails in the server that don't match any object "
|
|
||||||
'in OpenERP'
|
|
||||||
),
|
|
||||||
'match_first': fields.boolean(
|
|
||||||
'Use 1st match',
|
|
||||||
help='If there are multiple matches, use the first one. If '
|
|
||||||
'not checked, multiple matches count as no match at all'
|
|
||||||
),
|
|
||||||
'domain': fields.char(
|
|
||||||
'Domain', size=128, help='Fill in a search '
|
|
||||||
'filter to narrow down objects to match'
|
|
||||||
),
|
|
||||||
'msg_state': fields.selection(
|
|
||||||
[
|
|
||||||
('sent', 'Sent'),
|
|
||||||
('received', 'Received'),
|
|
||||||
],
|
|
||||||
'Message state',
|
|
||||||
help='The state messages fetched from this folder should be '
|
|
||||||
'assigned in OpenERP'
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
_defaults = {
|
|
||||||
'flag_nonmatching': True,
|
|
||||||
'msg_state': 'received',
|
|
||||||
}
|
|
||||||
|
|
||||||
def get_algorithm(self, cr, uid, ids, context=None):
|
|
||||||
for this in self.browse(cr, uid, ids, context):
|
|
||||||
return self._get_match_algorithms()[this.match_algorithm]()
|
|
||||||
|
|
||||||
def button_attach_mail_manually(self, cr, uid, ids, context=None):
|
|
||||||
for this in self.browse(cr, uid, ids, context):
|
|
||||||
context.update({'default_folder_id': this.id})
|
|
||||||
return {
|
|
||||||
'type': 'ir.actions.act_window',
|
|
||||||
'res_model': 'fetchmail.attach.mail.manually',
|
|
||||||
'target': 'new',
|
|
||||||
'context': context,
|
|
||||||
'view_type': 'form',
|
|
||||||
'view_mode': 'form',
|
|
||||||
}
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
Email gateway - folders
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Adds the possibility to attach emails from a certain IMAP folder to objects,
|
||||||
|
ie partners. Matching is done via several algorithms, ie email address, email
|
||||||
|
address's domain or the original Odoo algorithm.
|
||||||
|
|
||||||
|
This gives a simple possibility to archive emails in Odoo without a mail
|
||||||
|
client integration.
|
||||||
|
|
||||||
|
Configuration
|
||||||
|
=============
|
||||||
|
|
||||||
|
In your fetchmail configuration, you'll find a new field `folders`. Add your
|
||||||
|
folders here in IMAP notation [TODO]
|
||||||
|
|
||||||
|
Usage
|
||||||
|
=====
|
||||||
|
|
||||||
|
A widespread configuration is to have a shared mailbox with several folders [TODO]
|
||||||
|
|
||||||
|
Credits
|
||||||
|
=======
|
||||||
|
|
||||||
|
Contributors
|
||||||
|
------------
|
||||||
|
|
||||||
|
* Holger Brunn <hbrunn@therp.nl>
|
||||||
|
|
||||||
|
Icon
|
||||||
|
----
|
||||||
|
|
||||||
|
http://commons.wikimedia.org/wiki/File:Crystal_Clear_filesystem_folder_favorites.png
|
||||||
|
|
||||||
|
Maintainer
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. image:: http://odoo-community.org/logo.png
|
||||||
|
:alt: Odoo Community Association
|
||||||
|
:target: http://odoo-community.org
|
||||||
|
|
||||||
|
This module is maintained by the OCA.
|
||||||
|
|
||||||
|
OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.
|
||||||
|
|
||||||
|
To contribute to this module, please visit http://odoo-community.org.
|
|
@ -20,5 +20,6 @@
|
||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
import fetchmail_server
|
from . import match_algorithm
|
||||||
import fetchmail_server_folder
|
from . import model
|
||||||
|
from . import wizard
|
|
@ -21,15 +21,9 @@
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
{
|
{
|
||||||
'name': 'Attach mails in an IMAP folder to existing objects',
|
'name': 'Email gateway - folders',
|
||||||
|
'summary': 'Attach mails in an IMAP folder to existing objects',
|
||||||
'version': '1.0',
|
'version': '1.0',
|
||||||
'description': """
|
|
||||||
Adds the possibility to attach emails from a certain IMAP folder to objects,
|
|
||||||
ie partners. Matching is done via several algorithms, ie email address.
|
|
||||||
|
|
||||||
This gives a simple possibility to archive emails in OpenERP without a mail
|
|
||||||
client integration.
|
|
||||||
""",
|
|
||||||
'author': 'Therp BV',
|
'author': 'Therp BV',
|
||||||
'website': 'http://www.therp.nl',
|
'website': 'http://www.therp.nl',
|
||||||
"category": "Tools",
|
"category": "Tools",
|
||||||
|
@ -39,8 +33,6 @@ client integration.
|
||||||
'wizard/attach_mail_manually.xml',
|
'wizard/attach_mail_manually.xml',
|
||||||
'security/ir.model.access.csv',
|
'security/ir.model.access.csv',
|
||||||
],
|
],
|
||||||
'js': [],
|
'installable': True,
|
||||||
'installable': False,
|
'active': True,
|
||||||
'active': False,
|
|
||||||
'certificate': '',
|
|
||||||
}
|
}
|
|
@ -20,7 +20,7 @@
|
||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
import base
|
from . import base
|
||||||
import email_exact
|
from . import email_exact
|
||||||
import email_domain
|
from . import email_domain
|
||||||
import openerp_standard
|
from . import openerp_standard
|
|
@ -26,10 +26,10 @@ class base(object):
|
||||||
'''Name shown to the user'''
|
'''Name shown to the user'''
|
||||||
|
|
||||||
required_fields = []
|
required_fields = []
|
||||||
'''Fields on fetchmail_server folder that are required for this algorithm'''
|
'''Fields on fetchmail_server folder required for this algorithm'''
|
||||||
|
|
||||||
readonly_fields = []
|
readonly_fields = []
|
||||||
'''Fields on fetchmail_server folder that are readonly for this algorithm'''
|
'''Fields on fetchmail_server folder readonly for this algorithm'''
|
||||||
|
|
||||||
def search_matches(self, cr, uid, conf, mail_message, mail_message_org):
|
def search_matches(self, cr, uid, conf, mail_message, mail_message_org):
|
||||||
'''Returns ids found for model with mail_message'''
|
'''Returns ids found for model with mail_message'''
|
|
@ -20,7 +20,7 @@
|
||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
from email_exact import email_exact
|
from .email_exact import email_exact
|
||||||
|
|
||||||
|
|
||||||
class email_domain(email_exact):
|
class email_domain(email_exact):
|
|
@ -20,7 +20,7 @@
|
||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
from base import base
|
from .base import base
|
||||||
from openerp.tools.safe_eval import safe_eval
|
from openerp.tools.safe_eval import safe_eval
|
||||||
from openerp.tools.mail import email_split
|
from openerp.tools.mail import email_split
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
from base import base
|
from .base import base
|
||||||
|
|
||||||
|
|
||||||
class openerp_standard(base):
|
class openerp_standard(base):
|
|
@ -20,6 +20,5 @@
|
||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
import match_algorithm
|
from . import fetchmail_server
|
||||||
import model
|
from . import fetchmail_server_folder
|
||||||
import wizard
|
|
|
@ -19,33 +19,26 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
import logging
|
||||||
import base64
|
import base64
|
||||||
import simplejson
|
import simplejson
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
from openerp.osv.orm import Model, except_orm
|
from openerp import models, fields, api, exceptions
|
||||||
from openerp.tools.translate import _
|
from openerp.tools.translate import _
|
||||||
from openerp.osv import fields
|
|
||||||
from openerp.addons.fetchmail.fetchmail import _logger as logger
|
|
||||||
from openerp.tools.misc import UnquoteEvalContext
|
from openerp.tools.misc import UnquoteEvalContext
|
||||||
|
|
||||||
|
|
||||||
class fetchmail_server(Model):
|
class fetchmail_server(models.Model):
|
||||||
_inherit = 'fetchmail.server'
|
_inherit = 'fetchmail.server'
|
||||||
|
|
||||||
_columns = {
|
folder_ids = fields.One2many(
|
||||||
'folder_ids': fields.one2many(
|
'fetchmail.server.folder', 'server_id', 'Folders')
|
||||||
'fetchmail.server.folder', 'server_id', 'Folders'),
|
object_id = fields.Many2one(required=True)
|
||||||
}
|
|
||||||
|
|
||||||
_defaults = {
|
_defaults = {
|
||||||
'type': 'imap',
|
'type': 'imap',
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, pool, cr):
|
|
||||||
self._columns['object_id'].required = False
|
|
||||||
return super(fetchmail_server, self).__init__(pool, cr)
|
|
||||||
|
|
||||||
def onchange_server_type(
|
def onchange_server_type(
|
||||||
self, cr, uid, ids, server_type=False, ssl=False,
|
self, cr, uid, ids, server_type=False, ssl=False,
|
||||||
object_id=False):
|
object_id=False):
|
||||||
|
@ -75,111 +68,109 @@ class fetchmail_server(Model):
|
||||||
connection = this.connect()
|
connection = this.connect()
|
||||||
for folder in this.folder_ids:
|
for folder in this.folder_ids:
|
||||||
this.handle_folder(connection, folder)
|
this.handle_folder(connection, folder)
|
||||||
|
|
||||||
connection.close()
|
connection.close()
|
||||||
|
|
||||||
return super(fetchmail_server, self).fetch_mail(
|
return super(fetchmail_server, self).fetch_mail(
|
||||||
cr, uid, check_original, context)
|
cr, uid, check_original, context)
|
||||||
|
|
||||||
def handle_folder(self, cr, uid, ids, connection, folder, context=None):
|
@api.multi
|
||||||
|
def handle_folder(self, connection, folder):
|
||||||
'''Return ids of objects matched'''
|
'''Return ids of objects matched'''
|
||||||
|
|
||||||
matched_object_ids = []
|
matched_object_ids = []
|
||||||
|
|
||||||
for this in self.browse(cr, uid, ids, context=context):
|
for this in self:
|
||||||
logger.info('start checking for emails in %s server %s',
|
logging.info(
|
||||||
|
'start checking for emails in %s server %s',
|
||||||
folder.path, this.name)
|
folder.path, this.name)
|
||||||
|
|
||||||
match_algorithm = folder.get_algorithm()
|
match_algorithm = folder.get_algorithm()
|
||||||
|
|
||||||
if connection.select(folder.path)[0] != 'OK':
|
if connection.select(folder.path)[0] != 'OK':
|
||||||
logger.error(
|
logging.error(
|
||||||
'Could not open mailbox %s on %s' % (folder.path, this.server))
|
'Could not open mailbox %s on %s',
|
||||||
|
folder.path, this.server)
|
||||||
connection.select()
|
connection.select()
|
||||||
continue
|
continue
|
||||||
result, msgids = this.get_msgids(connection)
|
result, msgids = this.get_msgids(connection)
|
||||||
if result != 'OK':
|
if result != 'OK':
|
||||||
logger.error(
|
logging.error(
|
||||||
'Could not search mailbox %s on %s' % (
|
'Could not search mailbox %s on %s',
|
||||||
folder.path, this.server))
|
folder.path, this.server)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for msgid in msgids[0].split():
|
for msgid in msgids[0].split():
|
||||||
matched_object_ids += this.apply_matching(
|
matched_object_ids += this.apply_matching(
|
||||||
connection, folder, msgid, match_algorithm)
|
connection, folder, msgid, match_algorithm)
|
||||||
|
|
||||||
logger.info('finished checking for emails in %s server %s',
|
logging.info(
|
||||||
|
'finished checking for emails in %s server %s',
|
||||||
folder.path, this.name)
|
folder.path, this.name)
|
||||||
|
|
||||||
return matched_object_ids
|
return matched_object_ids
|
||||||
|
|
||||||
def get_msgids(self, cr, uid, ids, connection, context=None):
|
@api.multi
|
||||||
|
def get_msgids(self, connection):
|
||||||
'''Return imap ids of messages to process'''
|
'''Return imap ids of messages to process'''
|
||||||
return connection.search(None, 'UNDELETED')
|
return connection.search(None, 'UNDELETED')
|
||||||
|
|
||||||
def apply_matching(self, cr, uid, ids, connection, folder, msgid,
|
@api.multi
|
||||||
match_algorithm, context=None):
|
def apply_matching(self, connection, folder, msgid, match_algorithm):
|
||||||
'''Return ids of objects matched'''
|
'''Return ids of objects matched'''
|
||||||
|
|
||||||
matched_object_ids = []
|
matched_object_ids = []
|
||||||
|
|
||||||
for this in self.browse(cr, uid, ids, context=context):
|
for this in self:
|
||||||
result, msgdata = connection.fetch(msgid, '(RFC822)')
|
result, msgdata = connection.fetch(msgid, '(RFC822)')
|
||||||
|
|
||||||
if result != 'OK':
|
if result != 'OK':
|
||||||
logger.error(
|
logging.error(
|
||||||
'Could not fetch %s in %s on %s' % (msgid, folder.path, this.server))
|
'Could not fetch %s in %s on %s',
|
||||||
|
msgid, folder.path, this.server)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
mail_message = self.pool.get('mail.thread').message_parse(
|
mail_message = self.env['mail.thread'].message_parse(
|
||||||
cr, uid, msgdata[0][1], save_original=this.original,
|
msgdata[0][1], save_original=this.original)
|
||||||
context=context)
|
|
||||||
|
|
||||||
if self.pool.get('mail.message').search(
|
if self.env['mail.message'].search(
|
||||||
cr, uid, [
|
[('message_id', '=', mail_message['message_id'])]):
|
||||||
('message_id', '=', mail_message['message_id'])]):
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
found_ids = match_algorithm.search_matches(
|
found_ids = match_algorithm.search_matches(
|
||||||
cr, uid, folder,
|
self.env.cr, self.env.uid, folder, mail_message, msgdata[0][1])
|
||||||
mail_message, msgdata[0][1])
|
|
||||||
|
|
||||||
if found_ids and (len(found_ids) == 1 or
|
if found_ids and (len(found_ids) == 1 or
|
||||||
folder.match_first):
|
folder.match_first):
|
||||||
try:
|
try:
|
||||||
cr.execute('savepoint apply_matching')
|
self.env.cr.execute('savepoint apply_matching')
|
||||||
match_algorithm.handle_match(
|
match_algorithm.handle_match(
|
||||||
cr, uid, connection,
|
self.env.cr, self.env.uid, connection,
|
||||||
found_ids[0], folder, mail_message,
|
found_ids[0], folder, mail_message,
|
||||||
msgdata[0][1], msgid, context)
|
msgdata[0][1], msgid, self.env.context)
|
||||||
cr.execute('release savepoint apply_matching')
|
self.env.cr.execute('release savepoint apply_matching')
|
||||||
matched_object_ids += found_ids[:1]
|
matched_object_ids += found_ids[:1]
|
||||||
except Exception:
|
except Exception:
|
||||||
cr.execute('rollback to savepoint apply_matching')
|
self.env.cr.execute('rollback to savepoint apply_matching')
|
||||||
logger.exception(
|
logging.exception(
|
||||||
"Failed to fetch mail %s from %s",
|
"Failed to fetch mail %s from %s", msgid, this.name)
|
||||||
msgid, this.name)
|
|
||||||
elif folder.flag_nonmatching:
|
elif folder.flag_nonmatching:
|
||||||
connection.store(msgid, '+FLAGS', '\\FLAGGED')
|
connection.store(msgid, '+FLAGS', '\\FLAGGED')
|
||||||
|
|
||||||
return matched_object_ids
|
return matched_object_ids
|
||||||
|
|
||||||
def attach_mail(
|
@api.multi
|
||||||
self, cr, uid, ids, connection, object_id, folder,
|
def attach_mail(self, connection, object_id, folder, mail_message, msgid):
|
||||||
mail_message, msgid, context=None):
|
|
||||||
'''Return ids of messages created'''
|
'''Return ids of messages created'''
|
||||||
|
|
||||||
mail_message_ids = []
|
mail_message_ids = []
|
||||||
|
|
||||||
for this in self.browse(cr, uid, ids, context):
|
for this in self:
|
||||||
partner_id = None
|
partner_id = None
|
||||||
if folder.model_id.model == 'res.partner':
|
if folder.model_id.model == 'res.partner':
|
||||||
partner_id = object_id
|
partner_id = object_id
|
||||||
if 'partner_id' in self.pool.get(folder.model_id.model)._columns:
|
if 'partner_id' in self.env[folder.model_id.model]._columns:
|
||||||
partner_id = self.pool.get(
|
partner_id = self.env[folder.model_id.model].browse(object_id)\
|
||||||
folder.model_id.model).browse(
|
.partner_id.id
|
||||||
cr, uid, object_id, context
|
|
||||||
).partner_id.id
|
|
||||||
|
|
||||||
attachments = []
|
attachments = []
|
||||||
if this.attach and mail_message.get('attachments'):
|
if this.attach and mail_message.get('attachments'):
|
||||||
|
@ -196,13 +187,10 @@ class fetchmail_server(Model):
|
||||||
'res_id': object_id,
|
'res_id': object_id,
|
||||||
}
|
}
|
||||||
attachments.append(
|
attachments.append(
|
||||||
self.pool.get('ir.attachment').create(
|
self.env['ir.attachment'].create(data_attach))
|
||||||
cr, uid, data_attach, context=context))
|
|
||||||
|
|
||||||
mail_message_ids.append(
|
mail_message_ids.append(
|
||||||
self.pool.get('mail.message').create(
|
self.env['mail.message'].create({
|
||||||
cr, uid,
|
|
||||||
{
|
|
||||||
'author_id': partner_id,
|
'author_id': partner_id,
|
||||||
'model': folder.model_id.model,
|
'model': folder.model_id.model,
|
||||||
'res_id': object_id,
|
'res_id': object_id,
|
||||||
|
@ -212,18 +200,16 @@ class fetchmail_server(Model):
|
||||||
'email_from': mail_message.get('from'),
|
'email_from': mail_message.get('from'),
|
||||||
'date': mail_message.get('date'),
|
'date': mail_message.get('date'),
|
||||||
'message_id': mail_message.get('message_id'),
|
'message_id': mail_message.get('message_id'),
|
||||||
'attachment_ids': [(6, 0, attachments)],
|
'attachment_ids': [(6, 0, [a.id for a in attachments])],
|
||||||
},
|
}))
|
||||||
context))
|
|
||||||
|
|
||||||
if folder.delete_matching:
|
if folder.delete_matching:
|
||||||
connection.store(msgid, '+FLAGS', '\\DELETED')
|
connection.store(msgid, '+FLAGS', '\\DELETED')
|
||||||
return mail_message_ids
|
return mail_message_ids
|
||||||
|
|
||||||
def button_confirm_login(self, cr, uid, ids, context=None):
|
def button_confirm_login(self, cr, uid, ids, context=None):
|
||||||
retval = super(fetchmail_server, self).button_confirm_login(cr, uid,
|
retval = super(fetchmail_server, self).button_confirm_login(
|
||||||
ids,
|
cr, uid, ids, context)
|
||||||
context)
|
|
||||||
|
|
||||||
for this in self.browse(cr, uid, ids, context):
|
for this in self.browse(cr, uid, ids, context):
|
||||||
this.write({'state': 'draft'})
|
this.write({'state': 'draft'})
|
||||||
|
@ -231,9 +217,8 @@ class fetchmail_server(Model):
|
||||||
connection.select()
|
connection.select()
|
||||||
for folder in this.folder_ids:
|
for folder in this.folder_ids:
|
||||||
if connection.select(folder.path)[0] != 'OK':
|
if connection.select(folder.path)[0] != 'OK':
|
||||||
raise except_orm(
|
raise exceptions.ValidationError(
|
||||||
_('Error'), _('Mailbox %s not found!') %
|
_('Mailbox %s not found!') % folder.path)
|
||||||
folder.path)
|
|
||||||
connection.close()
|
connection.close()
|
||||||
this.write({'state': 'done'})
|
this.write({'state': 'done'})
|
||||||
|
|
||||||
|
@ -249,7 +234,7 @@ class fetchmail_server(Model):
|
||||||
result['fields']['folder_ids']['views']['form']['arch'])
|
result['fields']['folder_ids']['views']['form']['arch'])
|
||||||
modifiers = {}
|
modifiers = {}
|
||||||
docstr = ''
|
docstr = ''
|
||||||
for algorithm in self.pool.get('fetchmail.server.folder')\
|
for algorithm in self.pool['fetchmail.server.folder']\
|
||||||
._get_match_algorithms().itervalues():
|
._get_match_algorithms().itervalues():
|
||||||
for modifier in ['required', 'readonly']:
|
for modifier in ['required', 'readonly']:
|
||||||
for field in getattr(algorithm, modifier + '_fields'):
|
for field in getattr(algorithm, modifier + '_fields'):
|
||||||
|
@ -262,7 +247,7 @@ class fetchmail_server(Model):
|
||||||
docstr += _(algorithm.name) + '\n' + _(algorithm.__doc__) + \
|
docstr += _(algorithm.name) + '\n' + _(algorithm.__doc__) + \
|
||||||
'\n\n'
|
'\n\n'
|
||||||
|
|
||||||
for field in view:
|
for field in view.xpath('//field'):
|
||||||
if field.tag == 'field' and field.get('name') in modifiers:
|
if field.tag == 'field' and field.get('name') in modifiers:
|
||||||
field.set('modifiers', simplejson.dumps(
|
field.set('modifiers', simplejson.dumps(
|
||||||
dict(
|
dict(
|
|
@ -0,0 +1,115 @@
|
||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
##############################################################################
|
||||||
|
#
|
||||||
|
# OpenERP, Open Source Management Solution
|
||||||
|
# This module copyright (C) 2013 Therp BV (<http://therp.nl>)
|
||||||
|
# All Rights Reserved
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
########################################################################
|
||||||
|
from openerp import api, models, fields
|
||||||
|
from .. import match_algorithm
|
||||||
|
|
||||||
|
|
||||||
|
class fetchmail_server_folder(models.Model):
|
||||||
|
_name = 'fetchmail.server.folder'
|
||||||
|
_rec_name = 'path'
|
||||||
|
|
||||||
|
def _get_match_algorithms(self):
|
||||||
|
def get_all_subclasses(cls):
|
||||||
|
return (cls.__subclasses__() +
|
||||||
|
[subsub
|
||||||
|
for sub in cls.__subclasses__()
|
||||||
|
for subsub in get_all_subclasses(sub)])
|
||||||
|
return dict([(cls.__name__, cls)
|
||||||
|
for cls in get_all_subclasses(
|
||||||
|
match_algorithm.base.base)])
|
||||||
|
|
||||||
|
def _get_match_algorithms_sel(self):
|
||||||
|
algorithms = []
|
||||||
|
for cls in self._get_match_algorithms().itervalues():
|
||||||
|
algorithms.append((cls.__name__, cls.name))
|
||||||
|
algorithms.sort()
|
||||||
|
return algorithms
|
||||||
|
|
||||||
|
sequence = fields.Integer('Sequence')
|
||||||
|
path = fields.Char(
|
||||||
|
'Path',
|
||||||
|
help="The path to your mail folder. Typically would be something like "
|
||||||
|
"'INBOX.myfolder'", required=True)
|
||||||
|
model_id = fields.Many2one(
|
||||||
|
'ir.model', 'Model', required=True,
|
||||||
|
help='The model to attach emails to')
|
||||||
|
model_field = fields.Char(
|
||||||
|
'Field (model)',
|
||||||
|
help='The field in your model that contains the field to match '
|
||||||
|
'against.\n'
|
||||||
|
'Examples:\n'
|
||||||
|
"'email' if your model is res.partner, or "
|
||||||
|
"'partner_id.email' if you're matching sale orders")
|
||||||
|
model_order = fields.Char(
|
||||||
|
'Order (model)',
|
||||||
|
help='Field(s) to order by, this mostly useful in conjunction '
|
||||||
|
"with 'Use 1st match'")
|
||||||
|
match_algorithm = fields.Selection(
|
||||||
|
_get_match_algorithms_sel,
|
||||||
|
'Match algorithm', required=True,
|
||||||
|
help='The algorithm used to determine which object an email matches.')
|
||||||
|
mail_field = fields.Char(
|
||||||
|
'Field (email)',
|
||||||
|
help='The field in the email used for matching. Typically '
|
||||||
|
"this is 'to' or 'from'")
|
||||||
|
server_id = fields.Many2one('fetchmail.server', 'Server')
|
||||||
|
delete_matching = fields.Boolean(
|
||||||
|
'Delete matches',
|
||||||
|
help='Delete matched emails from server')
|
||||||
|
flag_nonmatching = fields.Boolean(
|
||||||
|
'Flag nonmatching',
|
||||||
|
help="Flag emails in the server that don't match any object in Odoo")
|
||||||
|
match_first = fields.Boolean(
|
||||||
|
'Use 1st match',
|
||||||
|
help='If there are multiple matches, use the first one. If '
|
||||||
|
'not checked, multiple matches count as no match at all')
|
||||||
|
domain = fields.Char(
|
||||||
|
'Domain',
|
||||||
|
help='Fill in a search filter to narrow down objects to match')
|
||||||
|
msg_state = fields.Selection(
|
||||||
|
[
|
||||||
|
('sent', 'Sent'),
|
||||||
|
('received', 'Received'),
|
||||||
|
],
|
||||||
|
'Message state',
|
||||||
|
help='The state messages fetched from this folder should be '
|
||||||
|
'assigned in Odoo')
|
||||||
|
|
||||||
|
_defaults = {
|
||||||
|
'flag_nonmatching': True,
|
||||||
|
'msg_state': 'received',
|
||||||
|
}
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def get_algorithm(self):
|
||||||
|
return self._get_match_algorithms()[self.match_algorithm]()
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def button_attach_mail_manually(self):
|
||||||
|
return {
|
||||||
|
'type': 'ir.actions.act_window',
|
||||||
|
'res_model': 'fetchmail.attach.mail.manually',
|
||||||
|
'target': 'new',
|
||||||
|
'context': dict(self.env.context, default_folder_id=self.id),
|
||||||
|
'view_type': 'form',
|
||||||
|
'view_mode': 'form',
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
|
@ -20,4 +20,4 @@
|
||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
import attach_mail_manually
|
from . import attach_mail_manually
|
Loading…
Reference in New Issue