Skip to content

Commit 16e1500

Browse files
committed
Merge pull request #65 from resulto-admin/ISSUE-56
Added support for attachments. Resolves #56
2 parents ea1112b + b001585 commit 16e1500

File tree

3 files changed

+114
-0
lines changed

3 files changed

+114
-0
lines changed

docs/resources/transmissions.rst

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,33 @@ Using inline templates and/or recipients
5454
)
5555
5656
57+
Sending an attachment
58+
*********************
59+
60+
.. code-block:: python
61+
62+
from sparkpost import SparkPost
63+
64+
sp = SparkPost()
65+
66+
sp.transmission.send(
67+
recipients=['[email protected]'],
68+
text="Hello world",
69+
html='<p>Hello world</p>',
70+
from_email='[email protected]',
71+
subject='Hello from python-sparkpost',
72+
track_opens=True,
73+
track_clicks=True,
74+
attachments=[
75+
{
76+
"name": "test.txt",
77+
"type": "text/plain",
78+
"filename": "/home/sparkpost/a-file.txt"
79+
}
80+
]
81+
)
82+
83+
5784
Using a stored template
5885
***********************
5986

sparkpost/transmissions.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import base64
12
import json
23

34
from .base import Resource
@@ -50,8 +51,31 @@ def _translate_keys(self, **kwargs):
5051
recipients = kwargs.get('recipients', [])
5152
model['recipients'] = self._extractRecipients(recipients)
5253

54+
attachments = kwargs.get('attachments', [])
55+
model['content']['attachments'] = self._extract_attachments(
56+
attachments)
57+
5358
return model
5459

60+
def _extract_attachments(self, attachments):
61+
formatted_attachments = []
62+
for attachment in attachments:
63+
formatted_attachment = {}
64+
formatted_attachment['type'] = attachment.get('type')
65+
formatted_attachment['name'] = attachment.get('name')
66+
if 'filename' in attachment:
67+
formatted_attachment['data'] = self._get_base64_from_file(
68+
attachment['filename'])
69+
else:
70+
formatted_attachment['data'] = attachment.get('data')
71+
formatted_attachments.append(formatted_attachment)
72+
return formatted_attachments
73+
74+
def _get_base64_from_file(self, filename):
75+
with open(filename, "rb") as a_file:
76+
encoded_string = base64.b64encode(a_file.read()).decode("ascii")
77+
return encoded_string
78+
5579
def _extractRecipients(self, recipients):
5680
formatted_recipients = []
5781
for recip in recipients:
@@ -86,6 +110,11 @@ def send(self, **kwargs):
86110
:param dict substitution_data: Corresponds to substitutions in
87111
html/text content. See `substitutions reference
88112
<https://www.sparkpost.com/docs/substitutions-reference>`_.
113+
:param dict attachments: Corresponds to attachments.
114+
See `Attachment Attributes reference
115+
<https://developers.sparkpost.com/api/#/reference/transmissions>`_.
116+
Replace `data` by `filename` if you want the library to perform
117+
the base64 conversion. Example: `"filename": "/full/path/test.txt"`
89118
:param str start_time: Delay generation of messages until this
90119
datetime. Format YYYY-MM-DDTHH:MM:SS+-HH:MM. Example:
91120
'2015-02-11T08:00:00-04:00'.

test/test_transmissions.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1+
import base64
2+
import json
3+
import os
4+
import tempfile
5+
16
import pytest
27
import responses
8+
import six
39

410
from sparkpost import SparkPost
511
from sparkpost import Transmissions
@@ -37,6 +43,58 @@ def test_success_send():
3743
assert results == 'yay'
3844

3945

46+
@responses.activate
47+
def test_success_send_with_attachments():
48+
try:
49+
# Let's compare unicode for Python 2 / 3 compatibility
50+
test_content = six.u("Hello \nWorld\n")
51+
(_, temp_file_path) = tempfile.mkstemp()
52+
with open(temp_file_path, "w") as temp_file:
53+
temp_file.write(test_content)
54+
55+
responses.add(
56+
responses.POST,
57+
'https://api.sparkpost.com/api/v1/transmissions',
58+
status=200,
59+
content_type='application/json',
60+
body='{"results": "yay"}'
61+
)
62+
sp = SparkPost('fake-key')
63+
64+
attachment = {
65+
"name": "test.txt",
66+
"type": "text/plain",
67+
"filename": temp_file_path
68+
}
69+
results = sp.transmission.send(attachments=[attachment])
70+
71+
request_params = json.loads(responses.calls[0].request.body)
72+
content = base64.b64decode(
73+
request_params["content"]["attachments"][0]["data"])
74+
# Let's compare unicode for Python 2 / 3 compatibility
75+
assert test_content == content.decode("ascii")
76+
77+
assert results == 'yay'
78+
79+
attachment = {
80+
"name": "test.txt",
81+
"type": "text/plain",
82+
"data": base64.b64encode(
83+
test_content.encode("ascii")).decode("ascii")
84+
}
85+
results = sp.transmission.send(attachments=[attachment])
86+
87+
request_params = json.loads(responses.calls[1].request.body)
88+
content = base64.b64decode(
89+
request_params["content"]["attachments"][0]["data"])
90+
# Let's compare unicode for Python 2 / 3 compatibility
91+
assert test_content == content.decode("ascii")
92+
93+
assert results == 'yay'
94+
finally:
95+
os.unlink(temp_file_path)
96+
97+
4098
@responses.activate
4199
def test_fail_send():
42100
responses.add(

0 commit comments

Comments
 (0)