Add MMS sending capacilities #1

Merged
alex merged 12 commits from dev into master 2021-05-21 05:57:05 +00:00
2 changed files with 61 additions and 46 deletions
Showing only changes of commit 127e5cffe3 - Show all commits

View file

@ -17,12 +17,14 @@ By default:
- python3 - python3
- python3-aiosmtpd - python3-aiosmtpd
- python3-pydbus
- python-messaging (pip install python-messaging) - python-messaging (pip install python-messaging)
### setup ### setup
Install the dependency and mms2mail (on debian based distribution): Install the dependency and mms2mail (on debian based distribution):
``` ```
sudo apt-get install python3 sudo apt-get install python3
sudo apt-get install python3-pydbus
sudo apt-get install python3-aiosmtpd sudo apt-get install python3-aiosmtpd
pip install --user python-messaging pip install --user python-messaging

View file

@ -14,8 +14,7 @@ import mailbox
import email import email
from gi.repository import GLib from gi.repository import GLib
import dbus import pydbus
import dbus.mainloop.glib
import os import os
import re import re
@ -115,7 +114,7 @@ class MMS2Mail:
return None return None
return status['info']['state'] return status['info']['state']
def message_added(self, name, value, member, path, interface): def message_added(self, name, value):
"""Trigger conversion on MessageAdded signal.""" """Trigger conversion on MessageAdded signal."""
if value['Status'] == 'downloaded' or value['Status'] == 'received': if value['Status'] == 'downloaded' or value['Status'] == 'received':
log.debug(f"New incoming MMS found ({name.split('/')[-1]})") log.debug(f"New incoming MMS found ({name.split('/')[-1]})")
@ -309,6 +308,7 @@ class Mail2MMSHandler:
recipients = [] recipients = []
attachments = [] attachments = []
smil = None smil = None
for r in envelope.rcpt_tos: for r in envelope.rcpt_tos:
number = r.split('@')[0] number = r.split('@')[0]
if self.pattern.search(number): if self.pattern.search(number):
@ -321,6 +321,7 @@ class Mail2MMSHandler:
return '553 Requested action not taken: mailbox name not allowed' return '553 Requested action not taken: mailbox name not allowed'
mail = self.parser.parsebytes(envelope.content) mail = self.parser.parsebytes(envelope.content)
subject = mail.get('subject', failobj=None)
cid = 1 cid = 1
total_size = 0 total_size = 0
with tempfile.TemporaryDirectory(prefix='mailtomms-') as tmp_dir: with tempfile.TemporaryDirectory(prefix='mailtomms-') as tmp_dir:
@ -358,8 +359,11 @@ class Mail2MMSHandler:
elif total_size > self.total_max_attachment_size: elif total_size > self.total_max_attachment_size:
return '554 5.3.4 Message too big for system' return '554 5.3.4 Message too big for system'
try: try:
self.dbusmmsd.send_mms(recipients, attachments, smil) self.dbusmmsd.send_mms(recipients=recipients,
except dbus.exceptions.DBusException as e: attachments=attachments,
subject=subject,
smil=smil)
except Exception as e:
log.error(e) log.error(e)
return '421 mmsd service not available' return '421 mmsd service not available'
return '250 OK' return '250 OK'
@ -376,8 +380,7 @@ class DbusMMSd():
:type mms2mail: mms2mail() :type mms2mail: mms2mail()
""" """
self.mms2mail = mms2mail self.mms2mail = mms2mail
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) self.bus = pydbus.SessionBus()
self.bus = dbus.SessionBus()
def set_mms2mail(self, mms2mail): def set_mms2mail(self, mms2mail):
""" """
@ -395,9 +398,7 @@ class DbusMMSd():
:param dbus_path: the mms dbus path :param dbus_path: the mms dbus path
:type dbus_path: str :type dbus_path: str
""" """
message = dbus.proxies.Interface(self.bus.get_object('org.ofono.mms', message = self.bus.get('org.ofono.mms', dbus_path)
dbus_path),
'org.ofono.mms.Message')
log.debug(f"Marking MMS as read {dbus_path}") log.debug(f"Marking MMS as read {dbus_path}")
message.MarkRead() message.MarkRead()
@ -408,11 +409,7 @@ class DbusMMSd():
:param dbus_path: the mms dbus path :param dbus_path: the mms dbus path
:type dbus_path: str :type dbus_path: str
""" """
if self.disable_dbus: message = self.bus.get('org.ofono.mms', dbus_path)
return None
message = dbus.proxies.Interface(self.bus.get_object('org.ofono.mms',
dbus_path),
'org.ofono.mms.Message')
log.debug(f"Deleting MMS {dbus_path}") log.debug(f"Deleting MMS {dbus_path}")
message.Delete() message.Delete()
@ -423,13 +420,10 @@ class DbusMMSd():
:return the mmsd service :return the mmsd service
:rtype dbus.Interface :rtype dbus.Interface
""" """
manager = dbus.Interface(self.bus.get_object('org.ofono.mms', manager = self.bus.get('org.ofono.mms', '/org/ofono/mms')
'/org/ofono/mms'),
'org.ofono.mms.Manager')
services = manager.GetServices() services = manager.GetServices()
path = services[0][0] path = services[0][0]
service = dbus.Interface(self.bus.get_object('org.ofono.mms', path), service = self.bus.get('org.ofono.mms', path)
'org.ofono.mms.Service')
return service return service
def get_manager_config(self): def get_manager_config(self):
@ -442,7 +436,28 @@ class DbusMMSd():
service = self.get_service() service = self.get_service()
return service.GetProperties() return service.GetProperties()
def send_mms(self, recipients, attachments, smil=None): def get_send_message_version(self):
"""
Ask mmsd its SendMessage method Signature.
:return true if mmsd is mmsd-tng allowing Subject in mms
:rtype bool
"""
if not hasattr(self, 'mmsdtng'):
from xml.dom import minidom
mmsdtng = False
svc = self.get_service()
i = svc.Introspect()
dom = minidom.parseString(i)
for method in dom.getElementsByTagName('method'):
if method.getAttribute('name') == "SendMessage":
for arg in method.getElementsByTagName('arg'):
if arg.getAttribute('name') == 'options':
mmsdtng = True
self.mmsdtng = mmsdtng
return self.mmsdtng
def send_mms(self, recipients, attachments, subject=None, smil=None):
""" """
Ask mmsd to send a MMS. Ask mmsd to send a MMS.
@ -457,37 +472,35 @@ class DbusMMSd():
""" """
service = self.get_service() service = self.get_service()
mms_recipients = dbus.Array([], signature=dbus.Signature('s')) mmsdtng = self.get_send_message_version()
for r in recipients: if mmsdtng:
mms_recipients.append(dbus.String(r)) log.debug("Using mmsd-tng as backend")
option_list = {}
if subject:
log.debug(f"MMS Subject = {subject}")
option_list['Subject'] = GLib.Variant('s', subject)
if smil:
log.debug("Send MMS as Related")
option_list['smil'] = GLib.Variant('s', smil)
options = GLib.Variant('a{sv}', option_list)
path = service.SendMessage(recipients, options,
attachments)
else:
log.debug("Using mmsd as backend")
if smil: if smil:
log.debug("Send MMS as Related") log.debug("Send MMS as Related")
mms_smil = dbus.String(smil)
else: else:
log.debug("Send MMS as Mixed") log.debug("Send MMS as Mixed")
mms_smil = "" smil = ""
path = service.SendMessage(recipients, smil,
mms_attachments = dbus.Array([], signature=dbus.Signature('(sss)')) attachments)
for a in attachments:
log.debug("Attachment: ({})".format(a))
mms_attachments.append(dbus.Struct((dbus.String(a[0]),
dbus.String(a[1]),
dbus.String(a[2])
), signature=None))
path = service.SendMessage(mms_recipients, mms_smil, mms_attachments)
log.debug(path) log.debug(path)
def add_signal_receiver(self): def add_signal_receiver(self):
"""Add a signal receiver to the current bus.""" """Add a signal receiver to the current bus."""
if self.mms2mail: if self.mms2mail:
self.bus.add_signal_receiver(self.mms2mail.message_added, service = self.get_service()
bus_name="org.ofono.mms", service.onMessageAdded = self.mms2mail.message_added
signal_name="MessageAdded",
member_keyword="member",
path_keyword="path",
interface_keyword="interface")
return True return True
else: else:
return False return False