/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/util/simplemapi.py

  • Committer: Lukáš Lalinsky
  • Date: 2007-08-10 21:04:18 UTC
  • mto: (2681.1.26 send-bundle)
  • mto: This revision was merged to the branch mainline in revision 2736.
  • Revision ID: lalinsky@gmail.com-20070810210418-yqauivfuhktjnmr3
Don't send e-mails with multi-line subjects.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""
 
2
Based on this original script: http://www.kirbyfooty.com/simplemapi.py
 
3
 
 
4
Now works (and tested) with:
 
5
    Outlook Express, Outlook 97 and 2000, 
 
6
    Eudora, Incredimail and Mozilla Thunderbird (1.5.0.2)
 
7
 
 
8
Date   : 30 May 2006
 
9
Version: 1.0.0
 
10
 
 
11
John Popplewell
 
12
john@johnnypops.demon.co.uk
 
13
http://www.johnnypops.demon.co.uk/python/
 
14
 
 
15
Thanks to Werner F. Bruhin and Michele Petrazzo on the ctypes list.
 
16
"""
 
17
 
 
18
import os
 
19
from ctypes import *
 
20
 
 
21
FLAGS = c_ulong
 
22
LHANDLE = c_ulong
 
23
LPLHANDLE = POINTER(LHANDLE)
 
24
 
 
25
# Return codes
 
26
SUCCESS_SUCCESS = 0
 
27
MAPI_USER_ABORT = 1
 
28
# Recipient class
 
29
MAPI_ORIG       = 0
 
30
MAPI_TO         = 1
 
31
# Send flags
 
32
MAPI_LOGON_UI   = 1
 
33
MAPI_DIALOG     = 8
 
34
 
 
35
class MapiRecipDesc(Structure):
 
36
    _fields_ = [
 
37
        ('ulReserved',      c_ulong),
 
38
        ('ulRecipClass',    c_ulong),
 
39
        ('lpszName',        c_char_p),
 
40
        ('lpszAddress',     c_char_p),
 
41
        ('ulEIDSize',       c_ulong),
 
42
        ('lpEntryID',       c_void_p),
 
43
    ]
 
44
lpMapiRecipDesc  = POINTER(MapiRecipDesc)
 
45
lppMapiRecipDesc = POINTER(lpMapiRecipDesc)
 
46
 
 
47
class MapiFileDesc(Structure):
 
48
    _fields_ = [
 
49
        ('ulReserved',      c_ulong),
 
50
        ('flFlags',         c_ulong),
 
51
        ('nPosition',       c_ulong),
 
52
        ('lpszPathName',    c_char_p),
 
53
        ('lpszFileName',    c_char_p),
 
54
        ('lpFileType',      c_void_p),
 
55
    ]
 
56
lpMapiFileDesc = POINTER(MapiFileDesc)
 
57
 
 
58
class MapiMessage(Structure):
 
59
    _fields_ = [
 
60
        ('ulReserved',          c_ulong),
 
61
        ('lpszSubject',         c_char_p),
 
62
        ('lpszNoteText',        c_char_p),
 
63
        ('lpszMessageType',     c_char_p),
 
64
        ('lpszDateReceived',    c_char_p),
 
65
        ('lpszConversationID',  c_char_p),
 
66
        ('flFlags',             FLAGS),
 
67
        ('lpOriginator',        lpMapiRecipDesc),
 
68
        ('nRecipCount',         c_ulong),
 
69
        ('lpRecips',            lpMapiRecipDesc),
 
70
        ('nFileCount',          c_ulong),
 
71
        ('lpFiles',             lpMapiFileDesc),
 
72
    ]
 
73
lpMapiMessage = POINTER(MapiMessage)
 
74
 
 
75
MAPI                    = windll.mapi32
 
76
MAPISendMail            = MAPI.MAPISendMail
 
77
MAPISendMail.restype    = c_ulong
 
78
MAPISendMail.argtypes   = (LHANDLE, c_ulong, lpMapiMessage, FLAGS, c_ulong)
 
79
 
 
80
MAPIResolveName         = MAPI.MAPIResolveName
 
81
MAPIResolveName.restype = c_ulong
 
82
MAPIResolveName.argtypes= (LHANDLE, c_ulong, c_char_p, FLAGS, c_ulong, lppMapiRecipDesc)
 
83
 
 
84
MAPIFreeBuffer          = MAPI.MAPIFreeBuffer
 
85
MAPIFreeBuffer.restype  = c_ulong
 
86
MAPIFreeBuffer.argtypes = (c_void_p, )
 
87
 
 
88
MAPILogon               = MAPI.MAPILogon
 
89
MAPILogon.restype       = c_ulong
 
90
MAPILogon.argtypes      = (LHANDLE, c_char_p, c_char_p, FLAGS, c_ulong, LPLHANDLE)
 
91
 
 
92
MAPILogoff              = MAPI.MAPILogoff
 
93
MAPILogoff.restype      = c_ulong
 
94
MAPILogoff.argtypes     = (LHANDLE, c_ulong, FLAGS, c_ulong)
 
95
 
 
96
 
 
97
def _logon(profileName=None, password=None):
 
98
    pSession = LHANDLE()
 
99
    rc = MAPILogon(0, profileName, password, MAPI_LOGON_UI, 0, byref(pSession))
 
100
    if rc != SUCCESS_SUCCESS:
 
101
        raise WindowsError, "MAPI error %i" % rc
 
102
    return pSession
 
103
 
 
104
 
 
105
def _logoff(session):
 
106
    rc = MAPILogoff(session, 0, 0, 0)
 
107
    if rc != SUCCESS_SUCCESS:
 
108
        raise WindowsError, "MAPI error %i" % rc
 
109
 
 
110
 
 
111
def _resolveName(session, name):
 
112
    pRecipDesc = lpMapiRecipDesc()
 
113
    rc = MAPIResolveName(session, 0, name, 0, 0, byref(pRecipDesc))
 
114
    if rc != SUCCESS_SUCCESS:
 
115
        raise WindowsError, "MAPI error %i" % rc
 
116
    rd = pRecipDesc.contents
 
117
    name, address = rd.lpszName, rd.lpszAddress
 
118
    rc = MAPIFreeBuffer(pRecipDesc)
 
119
    if rc != SUCCESS_SUCCESS:
 
120
        raise WindowsError, "MAPI error %i" % rc
 
121
    return name, address
 
122
 
 
123
 
 
124
def _sendMail(session, recipient, subject, body, attach):
 
125
    nFileCount = len(attach)
 
126
    if attach: 
 
127
        MapiFileDesc_A = MapiFileDesc * len(attach) 
 
128
        fda = MapiFileDesc_A() 
 
129
        for fd, fa in zip(fda, attach): 
 
130
            fd.ulReserved = 0 
 
131
            fd.flFlags = 0 
 
132
            fd.nPosition = -1 
 
133
            fd.lpszPathName = fa 
 
134
            fd.lpszFileName = None 
 
135
            fd.lpFileType = None 
 
136
        lpFiles = fda
 
137
    else:
 
138
        lpFiles = lpMapiFileDesc()
 
139
 
 
140
    RecipWork = recipient.split(';')
 
141
    RecipCnt = len(RecipWork)
 
142
    MapiRecipDesc_A = MapiRecipDesc * len(RecipWork) 
 
143
    rda = MapiRecipDesc_A() 
 
144
    for rd, ra in zip(rda, RecipWork):
 
145
        rd.ulReserved = 0 
 
146
        rd.ulRecipClass = MAPI_TO
 
147
        try:
 
148
            rd.lpszName, rd.lpszAddress = _resolveName(session, ra)
 
149
        except WindowsError:
 
150
            # work-round for Mozilla Thunderbird
 
151
            rd.lpszName, rd.lpszAddress = None, ra
 
152
        rd.ulEIDSize = 0
 
153
        rd.lpEntryID = None
 
154
    recip = rda
 
155
 
 
156
    msg = MapiMessage(0, subject, body, None, None, None, 0, lpMapiRecipDesc(),
 
157
                      RecipCnt, recip,
 
158
                      nFileCount, lpFiles)
 
159
 
 
160
    rc = MAPISendMail(session, 0, byref(msg), MAPI_DIALOG, 0)
 
161
    if rc != SUCCESS_SUCCESS and rc != MAPI_USER_ABORT:
 
162
        raise WindowsError, "MAPI error %i" % rc
 
163
 
 
164
 
 
165
def SendMail(recipient, subject="", body="", attachfiles=""):
 
166
    """Post an e-mail message using Simple MAPI
 
167
    
 
168
    recipient - string: address to send to (multiple addresses separated with a semicolon)
 
169
    subject   - string: subject header
 
170
    body      - string: message text
 
171
    attach    - string: files to attach (multiple attachments separated with a semicolon)
 
172
    """
 
173
 
 
174
    attach = []
 
175
    AttachWork = attachfiles.split(';')
 
176
    for file in AttachWork:
 
177
        if os.path.exists(file):
 
178
            attach.append(file)
 
179
    attach = map(os.path.abspath, attach)
 
180
 
 
181
    restore = os.getcwd()
 
182
    try:
 
183
        session = _logon()
 
184
        try:
 
185
            _sendMail(session, recipient, subject, body, attach)
 
186
        finally:
 
187
            _logoff(session)
 
188
    finally:
 
189
        os.chdir(restore)
 
190
 
 
191
 
 
192
if __name__ == '__main__':
 
193
    import sys
 
194
    recipient = "test@johnnypops.demon.co.uk"
 
195
    subject = "Test Message Subject"
 
196
    body = "Hi,\r\n\r\nthis is a quick test message,\r\n\r\ncheers,\r\nJohn."
 
197
    attachment = sys.argv[0]
 
198
    SendMail(recipient, subject, body, attachment)