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.

139 lines
5.4 KiB

  1. import logging
  2. import shlex
  3. from odoo import models, fields, api, _
  4. _logger = logging.getLogger(__name__)
  5. class Fetchmail(models.Model):
  6. _inherit = 'fetchmail.server'
  7. check_mailbox_size = fields.Boolean("Check Size")
  8. mailbox_size_partner_ids = fields.Many2many(
  9. "res.partner", string="Contacts to notify",
  10. domain=[('email', '!=', False)]
  11. )
  12. @api.model
  13. def _check_mailboxes_size_cron(self):
  14. """ Method called by cron to fetch mails from servers """
  15. return self.search([
  16. ('state', '=', 'done'),
  17. ('type', '=', 'imap'),
  18. ('check_mailbox_size', '=', True)
  19. ])._check_mailbox_size()
  20. @api.multi
  21. def _check_mailbox_size(self):
  22. for server in self:
  23. result_msg = ''
  24. imap_server = None
  25. try:
  26. if not server.mailbox_size_partner_ids:
  27. continue
  28. result_msg += _('<h3>Server %s</h3>') % server.name
  29. _logger.info(
  30. "Starting to check mailbox size for server %s"
  31. % server.name)
  32. imap_server = server.connect()
  33. result, folders = imap_server.list()
  34. if result != "OK":
  35. raise Exception(_("Server responded %s") % result)
  36. result_msg += _(
  37. "<table>"
  38. "<thead>"
  39. "<tr>"
  40. "<th style=\"text-align:left\">Folder</th>"
  41. "<th style=\"text-align:right\"># Msg</th>"
  42. "<th style=\"text-align:right\">Size</th>"
  43. "</tr>"
  44. "</thead>"
  45. "<tbody>"
  46. )
  47. number_of_messages_all = 0
  48. size_all = 0
  49. for item in folders:
  50. x = shlex.split(item.decode())
  51. mailbox = x[-1]
  52. # Select the desired folder
  53. result, number_of_messages = imap_server.select(
  54. '"{}"'.format(mailbox), readonly=1)
  55. if result != 'OK':
  56. _logger.info(
  57. "Server %s responded %s for folder %s"
  58. % (server.name, number_of_messages, mailbox))
  59. continue
  60. number_of_messages_all += int(
  61. number_of_messages[0].decode())
  62. size_folder = 0
  63. # Go through all the messages in the selected folder
  64. typ, msg = imap_server.search(None, 'ALL')
  65. # Find the first and last messages
  66. m = [int(msg_part.decode()) for msg_part in msg[0].split()]
  67. m.sort()
  68. if m:
  69. message_set = "%d:%d" % (m[0], m[-1])
  70. result, sizes_response = imap_server.fetch(
  71. message_set, "(UID RFC822.SIZE)")
  72. for i in range(m[-1]):
  73. tmp = sizes_response[i].split()
  74. size_folder += int(tmp[-1].decode().replace(')', ''))
  75. else:
  76. size_folder = 0
  77. result_msg += (
  78. "<tr>"
  79. "<td style=\"text-align:left\">%s</td>"
  80. "<td style=\"text-align:right\">%i</td>"
  81. "<td style=\"text-align:right\">%s</td>"
  82. "</tr>"
  83. ) % (
  84. mailbox,
  85. int(number_of_messages[0].decode()),
  86. size_folder
  87. )
  88. size_all += size_folder
  89. result_msg += _(
  90. "</tbody>"
  91. "<tfoot>"
  92. "<tr>"
  93. "<td style=\"text-align:left;font-weight:bold\">Sum</td>"
  94. "<td style=\"text-align:right;font-weight:bold\">%i</td>"
  95. "<td style=\"text-align:right;font-weight:bold\">"
  96. "%10.3fMB</td>"
  97. "</tr>"
  98. "</tfoot>"
  99. "</table>"
  100. ) % (number_of_messages_all, size_all / 1e6)
  101. except Exception as e:
  102. result_msg = _(
  103. "An error occured while checking mailbox %s:<br/>%s"
  104. ) % (server.name, str(e))
  105. finally:
  106. if imap_server:
  107. imap_server.logout()
  108. if result_msg:
  109. self.env['mail.mail'].create({
  110. 'subject': _("Mailbox size for server %s") % server.name,
  111. 'body_html': result_msg,
  112. 'recipient_ids': [
  113. (6, 0, server.mailbox_size_partner_ids.ids)]
  114. })
  115. @api.model
  116. def _update_cron(self):
  117. res = super(Fetchmail, self)._update_cron()
  118. if self.env.context.get('fetchmail_cron_running'):
  119. return res
  120. try:
  121. cron = self.env.ref(
  122. 'mail_check_mailbox_size.ir_cron_check_mailbox_size')
  123. cron.toggle(model=self._name, domain=[
  124. ('state', '=', 'done'), ('type', '=', 'imap'),
  125. ('check_mailbox_size', '=', True),
  126. ])
  127. except ValueError:
  128. # Nevermind if ir_cron_check_mailbox_size cannot be found
  129. pass
  130. return res