-
Notifications
You must be signed in to change notification settings - Fork 0
/
mail_compose.py
115 lines (87 loc) · 4.06 KB
/
mail_compose.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
""" Pythonista UI element to display a modal mail compose view.
Display a modal mail compose view, with pre-populated contents, on top of
the currently displayed view.
A demo app is shown when the module is run as a script.
**Credits** -- This is based on `tdamdouni's code
<https://github.com/tdamdouni/Pythonista/blob/master/objc/mail.py>`_ and
`jsbain's code <https://gist.github.com/jsbain/f82be8d8840f86b387a4>`_, with
an improvement picked up in an `omz post
<https://forum.omz-software.com/topic/2060/presenting-viewcontroller/2>`_.
**Revision history**
- 17-Avr-2020 TPO - Initial release. """
import os
from typing import Callable, List, Optional
import objc_util
from objc_util import create_objc_class, NSData, NSObject, ObjCClass, \
ObjCInstance, on_main_thread, UIApplication
objc_util.retain = getattr(objc_util, 'retain', [])
objc_util.load_framework('MessageUI')
@on_main_thread
def mail_compose(
subject: str = "",
recipients: Optional[List[str]] = None,
body: str = "",
filename: str = '',
mime_type: str = '',
dismiss_callback: Optional[Callable[[], None]] = None) -> None:
""" Modal mail compose view.
Display a modal mail compose view, with pre-populated contents, on top of
the currently displayed view.
The function returns immediately. Use argument `dismiss_callback` if your
application needs to be notified when the compose view is dismissed.
Arguments
---------
subject: `str`, defaults to ``""``
Mail subject.
recipients: `Optional[List[str]]`, defaults to ``None``
List of mail addresses for the recipients of the email.
body: `str`, defaults to ``""``
Mail body.
filename: `str`, defaults to ``''``
If non-empty, name of a file to be attached to the email.
mime_type: `str`, defaults to ``''``
If `filename` is not empty, indicates the mime type of its contents,
for instance ``'image/gif'``
dismiss_callback: `Optional[Callable[[], None]]`, defaults to ``None``
When set to a callable, it is called (with no arguments) when the mail
composition view is dismissed. """
def mailComposeController_didFinishWithResult_error_(
self, sel, controller, result, error):
nonlocal dismiss_callback
mail_vc = ObjCInstance(controller)
mail_vc.setMailComposeDelegate_(None)
mail_vc.dismissViewControllerAnimated_completion_(True, None)
ObjCInstance(self).release()
if dismiss_callback:
dismiss_callback()
try:
MailDelegate = ObjCClass('MailDelegate')
except ValueError:
MailDelegate = create_objc_class(
'MailDelegate',
superclass=NSObject,
methods=[mailComposeController_didFinishWithResult_error_],
protocols=['MFMailComposeViewControllerDelegate'])
objc_util.retain.append(mailComposeController_didFinishWithResult_error_)
MFMailComposeViewController = ObjCClass('MFMailComposeViewController')
mail_vc = MFMailComposeViewController.alloc().init().autorelease()
delegate = MailDelegate.alloc().init().autorelease()
objc_util.retain.append(delegate)
mail_vc.setMailComposeDelegate_(delegate)
# Find a view controller which is not already presenting, see
# https://forum.omz-software.com/topic/2060/presenting-viewcontroller/2
root_vc = UIApplication.sharedApplication().keyWindow().rootViewController()
while root_vc.presentedViewController():
root_vc = root_vc.presentedViewController()
mail_vc.setSubject_(subject)
if recipients is not None:
mail_vc.setToRecipients_(recipients)
mail_vc.setMessageBody_isHTML_(body, body.startswith('<html>'))
if filename and os.path.exists(filename):
mail_vc.addAttachmentData_mimeType_fileName_(
NSData.dataWithContentsOfFile_(os.path.abspath(filename)),
mime_type,
filename)
root_vc.presentViewController_animated_completion_(mail_vc, True, None)
if __name__ == '__main__':
mail_compose(subject="Test", body="Your message here")