/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: Jelmer Vernooij
  • Date: 2011-12-19 10:58:39 UTC
  • mfrom: (6383 +trunk)
  • mto: This revision was merged to the branch mainline in revision 6386.
  • Revision ID: jelmer@canonical.com-20111219105839-uji05ck4rkm1mj4j
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from __future__ import absolute_import
 
2
"""
 
3
Copyright (c) 2007 Ian Cook and John Popplewell
 
4
 
 
5
Permission is hereby granted, free of charge, to any person obtaining
 
6
a copy of this software and associated documentation files (the
 
7
"Software"), to deal in the Software without restriction, including
 
8
without limitation the rights to use, copy, modify, merge, publish,
 
9
distribute, sublicense, and/or sell copies of the Software, and to
 
10
permit persons to whom the Software is furnished to do so, subject to
 
11
the following conditions:
 
12
 
 
13
The above copyright notice and this permission notice shall be included
 
14
in all copies or substantial portions of the Software.
 
15
 
 
16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
17
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
18
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
19
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 
20
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 
21
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 
22
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
23
 
 
24
Date    : 11 August 2007
 
25
Version : 1.0.1
 
26
Contact : John Popplewell
 
27
Email   : john@johnnypops.demon.co.uk
 
28
Web     : http://www.johnnypops.demon.co.uk/python/
 
29
Origin  : Based on the original script by Ian Cook
 
30
          http://www.kirbyfooty.com/simplemapi.py
 
31
Comments: Works (and tested) with:
 
32
          Outlook Express, Outlook 97 and 2000,
 
33
          Eudora, Incredimail and Mozilla Thunderbird (1.5.0.2)
 
34
Thanks  : Werner F. Bruhin and Michele Petrazzo on the ctypes list.
 
35
 
 
36
If you have any bug-fixes, enhancements or suggestions regarding this
 
37
software, please contact me at the above email address.
 
38
"""
 
39
 
 
40
import os
 
41
from ctypes import *
 
42
 
 
43
FLAGS = c_ulong
 
44
LHANDLE = c_ulong
 
45
LPLHANDLE = POINTER(LHANDLE)
 
46
 
 
47
# Return codes
 
48
SUCCESS_SUCCESS                 = 0
 
49
MAPI_USER_ABORT                 = 1
 
50
MAPI_E_USER_ABORT               = MAPI_USER_ABORT
 
51
MAPI_E_FAILURE                  = 2
 
52
MAPI_E_LOGON_FAILURE            = 3
 
53
MAPI_E_LOGIN_FAILURE            = MAPI_E_LOGON_FAILURE
 
54
MAPI_E_DISK_FULL                = 4
 
55
MAPI_E_INSUFFICIENT_MEMORY      = 5
 
56
MAPI_E_ACCESS_DENIED            = 6
 
57
MAPI_E_TOO_MANY_SESSIONS        = 8
 
58
MAPI_E_TOO_MANY_FILES           = 9
 
59
MAPI_E_TOO_MANY_RECIPIENTS      = 10
 
60
MAPI_E_ATTACHMENT_NOT_FOUND     = 11
 
61
MAPI_E_ATTACHMENT_OPEN_FAILURE  = 12
 
62
MAPI_E_ATTACHMENT_WRITE_FAILURE = 13
 
63
MAPI_E_UNKNOWN_RECIPIENT        = 14
 
64
MAPI_E_BAD_RECIPTYPE            = 15
 
65
MAPI_E_NO_MESSAGES              = 16
 
66
MAPI_E_INVALID_MESSAGE          = 17
 
67
MAPI_E_TEXT_TOO_LARGE           = 18
 
68
MAPI_E_INVALID_SESSION          = 19
 
69
MAPI_E_TYPE_NOT_SUPPORTED       = 20
 
70
MAPI_E_AMBIGUOUS_RECIPIENT      = 21
 
71
MAPI_E_AMBIG_RECIP              = MAPI_E_AMBIGUOUS_RECIPIENT
 
72
MAPI_E_MESSAGE_IN_USE           = 22
 
73
MAPI_E_NETWORK_FAILURE          = 23
 
74
MAPI_E_INVALID_EDITFIELDS       = 24
 
75
MAPI_E_INVALID_RECIPS           = 25
 
76
MAPI_E_NOT_SUPPORTED            = 26
 
77
# Recipient class
 
78
MAPI_ORIG       = 0
 
79
MAPI_TO         = 1
 
80
# Send flags
 
81
MAPI_LOGON_UI   = 1
 
82
MAPI_DIALOG     = 8
 
83
 
 
84
class MapiRecipDesc(Structure):
 
85
    _fields_ = [
 
86
        ('ulReserved',      c_ulong),
 
87
        ('ulRecipClass',    c_ulong),
 
88
        ('lpszName',        c_char_p),
 
89
        ('lpszAddress',     c_char_p),
 
90
        ('ulEIDSize',       c_ulong),
 
91
        ('lpEntryID',       c_void_p),
 
92
    ]
 
93
lpMapiRecipDesc  = POINTER(MapiRecipDesc)
 
94
lppMapiRecipDesc = POINTER(lpMapiRecipDesc)
 
95
 
 
96
class MapiFileDesc(Structure):
 
97
    _fields_ = [
 
98
        ('ulReserved',      c_ulong),
 
99
        ('flFlags',         c_ulong),
 
100
        ('nPosition',       c_ulong),
 
101
        ('lpszPathName',    c_char_p),
 
102
        ('lpszFileName',    c_char_p),
 
103
        ('lpFileType',      c_void_p),
 
104
    ]
 
105
lpMapiFileDesc = POINTER(MapiFileDesc)
 
106
 
 
107
class MapiMessage(Structure):
 
108
    _fields_ = [
 
109
        ('ulReserved',          c_ulong),
 
110
        ('lpszSubject',         c_char_p),
 
111
        ('lpszNoteText',        c_char_p),
 
112
        ('lpszMessageType',     c_char_p),
 
113
        ('lpszDateReceived',    c_char_p),
 
114
        ('lpszConversationID',  c_char_p),
 
115
        ('flFlags',             FLAGS),
 
116
        ('lpOriginator',        lpMapiRecipDesc),
 
117
        ('nRecipCount',         c_ulong),
 
118
        ('lpRecips',            lpMapiRecipDesc),
 
119
        ('nFileCount',          c_ulong),
 
120
        ('lpFiles',             lpMapiFileDesc),
 
121
    ]
 
122
lpMapiMessage = POINTER(MapiMessage)
 
123
 
 
124
MAPI                    = windll.mapi32
 
125
MAPISendMail            = MAPI.MAPISendMail
 
126
MAPISendMail.restype    = c_ulong
 
127
MAPISendMail.argtypes   = (LHANDLE, c_ulong, lpMapiMessage, FLAGS, c_ulong)
 
128
 
 
129
MAPIResolveName         = MAPI.MAPIResolveName
 
130
MAPIResolveName.restype = c_ulong
 
131
MAPIResolveName.argtypes= (LHANDLE, c_ulong, c_char_p, FLAGS, c_ulong, lppMapiRecipDesc)
 
132
 
 
133
MAPIFreeBuffer          = MAPI.MAPIFreeBuffer
 
134
MAPIFreeBuffer.restype  = c_ulong
 
135
MAPIFreeBuffer.argtypes = (c_void_p, )
 
136
 
 
137
MAPILogon               = MAPI.MAPILogon
 
138
MAPILogon.restype       = c_ulong
 
139
MAPILogon.argtypes      = (LHANDLE, c_char_p, c_char_p, FLAGS, c_ulong, LPLHANDLE)
 
140
 
 
141
MAPILogoff              = MAPI.MAPILogoff
 
142
MAPILogoff.restype      = c_ulong
 
143
MAPILogoff.argtypes     = (LHANDLE, c_ulong, FLAGS, c_ulong)
 
144
 
 
145
 
 
146
class MAPIError(WindowsError):
 
147
 
 
148
    def __init__(self, code):
 
149
        WindowsError.__init__(self)
 
150
        self.code = code
 
151
 
 
152
    def __str__(self):
 
153
        return 'MAPI error %d' % (self.code,)
 
154
 
 
155
 
 
156
def _logon(profileName=None, password=None):
 
157
    pSession = LHANDLE()
 
158
    rc = MAPILogon(0, profileName, password, MAPI_LOGON_UI, 0, byref(pSession))
 
159
    if rc != SUCCESS_SUCCESS:
 
160
        raise MAPIError, rc
 
161
    return pSession
 
162
 
 
163
 
 
164
def _logoff(session):
 
165
    rc = MAPILogoff(session, 0, 0, 0)
 
166
    if rc != SUCCESS_SUCCESS:
 
167
        raise MAPIError, rc
 
168
 
 
169
 
 
170
def _resolveName(session, name):
 
171
    pRecipDesc = lpMapiRecipDesc()
 
172
    rc = MAPIResolveName(session, 0, name, 0, 0, byref(pRecipDesc))
 
173
    if rc != SUCCESS_SUCCESS:
 
174
        raise MAPIError, rc
 
175
    rd = pRecipDesc.contents
 
176
    name, address = rd.lpszName, rd.lpszAddress
 
177
    rc = MAPIFreeBuffer(pRecipDesc)
 
178
    if rc != SUCCESS_SUCCESS:
 
179
        raise MAPIError, rc
 
180
    return name, address
 
181
 
 
182
 
 
183
def _sendMail(session, recipient, subject, body, attach):
 
184
    nFileCount = len(attach)
 
185
    if attach:
 
186
        MapiFileDesc_A = MapiFileDesc * len(attach)
 
187
        fda = MapiFileDesc_A()
 
188
        for fd, fa in zip(fda, attach):
 
189
            fd.ulReserved = 0
 
190
            fd.flFlags = 0
 
191
            fd.nPosition = -1
 
192
            fd.lpszPathName = fa
 
193
            fd.lpszFileName = None
 
194
            fd.lpFileType = None
 
195
        lpFiles = fda
 
196
    else:
 
197
        lpFiles = lpMapiFileDesc()
 
198
 
 
199
    RecipWork = recipient.split(';')
 
200
    RecipCnt = len(RecipWork)
 
201
    MapiRecipDesc_A = MapiRecipDesc * len(RecipWork)
 
202
    rda = MapiRecipDesc_A()
 
203
    for rd, ra in zip(rda, RecipWork):
 
204
        rd.ulReserved = 0
 
205
        rd.ulRecipClass = MAPI_TO
 
206
        try:
 
207
            rd.lpszName, rd.lpszAddress = _resolveName(session, ra)
 
208
        except WindowsError:
 
209
            # work-round for Mozilla Thunderbird
 
210
            rd.lpszName, rd.lpszAddress = None, ra
 
211
        rd.ulEIDSize = 0
 
212
        rd.lpEntryID = None
 
213
    recip = rda
 
214
 
 
215
    msg = MapiMessage(0, subject, body, None, None, None, 0, lpMapiRecipDesc(),
 
216
                      RecipCnt, recip,
 
217
                      nFileCount, lpFiles)
 
218
 
 
219
    rc = MAPISendMail(session, 0, byref(msg), MAPI_DIALOG, 0)
 
220
    if rc != SUCCESS_SUCCESS:
 
221
        raise MAPIError, rc
 
222
 
 
223
 
 
224
def SendMail(recipient, subject="", body="", attachfiles=""):
 
225
    """Post an e-mail message using Simple MAPI
 
226
 
 
227
    recipient - string: address to send to (multiple addresses separated with a semicolon)
 
228
    subject   - string: subject header
 
229
    body      - string: message text
 
230
    attach    - string: files to attach (multiple attachments separated with a semicolon)
 
231
    """
 
232
 
 
233
    attach = []
 
234
    AttachWork = attachfiles.split(';')
 
235
    for file in AttachWork:
 
236
        if os.path.exists(file):
 
237
            attach.append(file)
 
238
    attach = map(os.path.abspath, attach)
 
239
 
 
240
    restore = os.getcwd()
 
241
    try:
 
242
        session = _logon()
 
243
        try:
 
244
            _sendMail(session, recipient, subject, body, attach)
 
245
        finally:
 
246
            _logoff(session)
 
247
    finally:
 
248
        os.chdir(restore)
 
249
 
 
250
 
 
251
if __name__ == '__main__':
 
252
    import sys
 
253
    recipient = "test@johnnypops.demon.co.uk"
 
254
    subject = "Test Message Subject"
 
255
    body = "Hi,\r\n\r\nthis is a quick test message,\r\n\r\ncheers,\r\nJohn."
 
256
    attachment = sys.argv[0]
 
257
    SendMail(recipient, subject, body, attachment)
 
258