themartorana / python-postmark Goto Github PK
View Code? Open in Web Editor NEWPostmark library for Python 2.6 and greater
Home Page: http://davemartorana.com
License: MIT License
Postmark library for Python 2.6 and greater
Home Page: http://davemartorana.com
License: MIT License
If I send message with subject wrapped into ugettext_lazy, PostMark backend falls down with the following error:
...
File "/usr/local/lib/python2.7/site-packages/postmark/core.py", line 44, in default
return super(PMJSONEncoder, self).default(o)
File "/usr/local/lib/python2.7/site-packages/simplejson/encoder.py", line 252, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <django.utils.functional.__proxy__ object at 0x7f35c0e1fa10> is not JSON serializable
I've solved this bug locally with subject=str(subject)
.
I think the best solution may be wrap subject and message body into str
.
Version 0.5.5
Python 3.7.5
Django 2.2.10
Attempt to attach a file to a new PMMail message as a byte string, using the list of tuples format, and send() it.
message = PMMail(
api_key=os.environ.get('POSTMARK_API_KEY'),
subject=subject,
sender=os.environ.get('POSTMARK_SENDER'),
to=recipient,
text_body=text_body,
html_body=html_body,
attachments=attachments,
tag=tag)
message.send()
Where
attachments = [
(
"csv_file.csv",
b'TXkgbmV3IHN0cmluZy4=',
"text/csv"
)
]
Error returned is:
[('csv_file.csv', b'TXkgbmV3IHN0cmluZy4=', 'text/csv')]
Object of type bytes is not JSON serializable
Traceback (most recent call last):
File "/app/apps/chipapp/tasks/emails.py", line 451, in _send_email_with_attachments
message.send()
File "/app/.heroku/python/lib/python3.7/site-packages/postmark/core.py", line 513, in send
json.dumps(json_message, cls=PMJSONEncoder).encode('utf8'),
File "/app/.heroku/python/lib/python3.7/json/__init__.py", line 238, in dumps
**kw).encode(obj)
File "/app/.heroku/python/lib/python3.7/json/encoder.py", line 199, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/app/.heroku/python/lib/python3.7/json/encoder.py", line 257, in iterencode
return _iterencode(o, 0)
File "/app/.heroku/python/lib/python3.7/site-packages/postmark/core.py", line 40, in default
return super(PMJSONEncoder, self).default(o)
File "/app/.heroku/python/lib/python3.7/json/encoder.py", line 179, in default
raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type bytes is not JSON serializable
I'm running Python 2.6.5 (version in the Ubuntu repository) on Ubuntu 10.04. Here is the traceback.
Traceback (most recent call last):
File "./postmark_demo.py", line 24, in <module>
pmm.send()
File "/usr/local/lib/python2.6/dist-packages/postmark/core.py", line 350, in send
elif isinstance(attachment, email.mime.base.MIMEBase):
AttributeError: 'module' object has no attribute 'base'
The module, for whatever reason (Python packages are still a bit weird to me), isn't accessible when just email
is imported. If the module is imported at the top as email.mime.base
instead of as email
, this problem would be fixed without even needing to change line 350. The email
module isn't used anywhere else in this file, so I don't think it would be an issue.
[I also had a question which I have since answered.]
Postmark added a new field TemplateAlias which can be used instead of TemplateId to reference templates across servers.
If I send three messages, but one of the messages doesn't have a recipient, then at this stage the pm_messages list will have only two elements.
How is user-code supposed to figure out which of the three messages didn't get send? That is, after this point, there's no difference between:
connection.send_messages([wrong_message, correct_message1, correct_message2])
connection.send_messages([correct_message1, wrong_message, correct_message2])
connection.send_messages([correct_message1, correct_message2, wrong_message])
Would be great if the return value could then be
[None, message_id1, message_id2]
[message_id1, None, message_id2]
[message_id1, message_id2, None]
in these cases?
I have created simple mixin for Tornado.
https://github.com/tigrus/postmark-tornado
Can you merge it into python-postmark?
Postmark returns a json document containing the MessageID of the recently submitted email. PMMail.send() just returns True if all went well. Wouldn't it be better to return the MessageID if things went well?! This MessageID is necessary when writing a bouncehook: http://developer.postmarkapp.com/developer-bounces.html#bounce-hooks
Heya, I've got Sentry reporting running on it's own Arch Linux server, quite happily. But when I add the Postmark details to the "/etc/sentry.conf.py" using python-postmark it simply has no idea what's going on, I'm not getting any errors but no mails are getting through, or test results.
Any ideas would be amazing:
Contents of "/etc/sentry.conf.py":
EMAIL_BACKEND = 'postmark.django_backend.EmailBackend'
SERVER_EMAIL = '[email protected]'
POSTMARK_API_KEY = 'API_KEY'
POSTMARK_SENDER = '[email protected]'
POSTMARK_TEST_MODE = False
Cheers,
d.
Could you please update the tags in this repo? Looks like the current version is 5.1 but there are only tags through 4.x.
Thanks.
The workaround is to use EmailMultiAlternatives, but it would be nice if content_subtype worked as well considering there are some cases where a plaintext alternative is not necessary.
Currently the Postmark API supports sending email Metadata but this package does not. I'm trying to use this data to correlate Postmark "bounce" webhooks to rows in my own system. Maybe it's here and I didn't see it but I couldn't find any references.
https://postmarkapp.com/developer/api/email-api#send-a-single-email
https://postmarkapp.com/updates/custom-metadata-for-your-emails
The Django backend has to do this all by itself right now:
https://github.com/themartorana/python-postmark/blob/master/postmark/django_backend.py#L58
As of this writing, distribute is deprecated since it's been merged back into setuptools.
Currently, python-postmark doesn't work without distribute.
The specific issue I'm having is that we'd like to suppress PMMailUnprocessableEntityException caused by (django.contrib.auth) password resets. While I'd like to be that specific, I see that you already have a fail_silently setting that would suppress all _send() exceptions, and I'd be OK with that but don't see how to set it.
Thanks,
Jim Phares
The API appears to support a ContentID being specified in an attachment. However, the current version of python-postmark does not appear to pass this through when setting attachments.
Sending an email with an attachment fails because this line:
python-postmark/postmark/django_backend.py
Line 101 in 3fb0e96
sets the content to a bytestring on Python 3:
https://docs.python.org/3/library/base64.html#base64.encodestring
(By the way, encodestring
is deprecated, you might want to fix that.)
Stack trace
Traceback (most recent call last):
File "<project_name>/users/models.py", line 268, in email_user
mail.send()
File "/app/.heroku/python/lib/python3.5/site-packages/django/core/mail/message.py", line 342, in send
return self.get_connection(fail_silently).send_messages([self])
File "/app/.heroku/python/lib/python3.5/site-packages/postmark/django_backend.py", line 61, in send_messages
sent = self._send(email_messages)
File "/app/.heroku/python/lib/python3.5/site-packages/postmark/django_backend.py", line 139, in _send
to_send.send(test=self.test_mode)
File "/app/.heroku/python/lib/python3.5/site-packages/postmark/core.py", line 436, in send
json.dumps(json_message, cls=PMJSONEncoder).encode('utf8'),
File "/app/.heroku/python/lib/python3.5/json/__init__.py", line 237, in dumps
**kw).encode(obj)
File "/app/.heroku/python/lib/python3.5/json/encoder.py", line 198, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/app/.heroku/python/lib/python3.5/json/encoder.py", line 256, in iterencode
return _iterencode(o, 0)
File "/app/.heroku/python/lib/python3.5/site-packages/postmark/core.py", line 44, in default
return super(PMJSONEncoder, self).default(o)
File "/app/.heroku/python/lib/python3.5/json/encoder.py", line 179, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: b'JVBERi0xLjMKJeLjz9MKMSAwIG9iago8PC9D... <the whole attachememt, base 64 encoded>
Reproduction code
def email_user(self, subject, message,
from_email=None, recipient_list=None, html_message=None,
attachments=None, **kwargs):
"""
Send an email to this user. Copied from AbstractUser.email_user.
"""
if recipient_list is None:
recipient_list = [self.email]
mail = EmailMultiAlternatives(subject, message,
from_email, recipient_list)
if html_message is not None:
mail.attach_alternative(html_message, 'text/html')
if attachments is not None:
for attachment in attachments:
mail.attach(*attachment)
mail.send()
An attachement is defined as follows:
Attachment = collections.namedtuple(
'Attachment',
[
'filename',
'content',
'content_type',
],
)
attachment = Attachment(
filename=os.path.basename(document.name),
content=document.read(),
content_type='application/pdf',
)
Hello,
I try to send local PDF files but isn't work,
with open(src_pdf, 'rb') as f:
pdf_file = f.read()
attachments = [
("my_pdf_file.pdf", pdf_file, 'application/pdf')
]
pm = PMMail(
to=user_mail,
bcc=pmBCC,
sender=pmSender,
template_id=email_template_id,
template_model=template_model,
api_key=pmApiKey,
attachments=attachments,
tag=pmTag)
pm.send()
do you know what is wrong?
Thanks
I migrated to python 3 and this code is now breaking:
/Users/lemon/workspace/projectb/emails/trigger.py in postmark_send(subject, html_body, to_info, from_info, cc_info, replyto_info, bcc_info)
22 reply_to=replyto_info,
23 )
---> 24 return pm.send()
25
26
/usr/local/lib/python3.3/site-packages/postmark/core.py in send(self, test)
460 result.close()
461 if result.code == 200:
--> 462 self.message_id = json.loads(jsontxt).get('MessageID', None)
463 return True
464 else:
/usr/local/Cellar/python3/3.3.5/Frameworks/Python.framework/Versions/3.3/lib/python3.3/json/__init__.py in loads(s, encoding, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, **kw)
314 parse_int is None and parse_float is None and
315 parse_constant is None and object_pairs_hook is None and not kw):
--> 316 return _default_decoder.decode(s)
317 if cls is None:
318 cls = JSONDecoder
/usr/local/Cellar/python3/3.3.5/Frameworks/Python.framework/Versions/3.3/lib/python3.3/json/decoder.py in decode(self, s, _w)
349
350 """
--> 351 obj, end = self.raw_decode(s, idx=_w(s, 0).end())
352 end = _w(s, end).end()
353 if end != len(s):
TypeError: can't use a string pattern on a bytes-like object
I believe jsontxt
needs a .decode()
The message sends, but the error would have you believe otherwise (and messes up your application logic).
I am not sure if this is a lmitiation of your lib or of postmark itself
File ".../.venv/lib/python2.7/site-packages/postmark/core.py", line 875, in activate
h1 = HTTPConnection('api.postmarkapp.com')
NameError: global name 'HTTPConnection' is not defined
Python 2.7.13. Seems to be the only place in that file that uses this class.
Latest version on PyPi is 0.4.7. It would be helpful if versions there matched active development on github, i.e. version 0.4.9 at this point.
Thanks!
I tried sending batch with templates but it doesn't seem to work. If I send it without templates it works as intended.
While browsing through the code I found that 'email/batch' is hard-coded.
I looked at Postmarks API documentation https://postmarkapp.com/developer/api/templates-api#send-batch-with-templates and found that there's a different call for sending batch with templates. I don't know if it has worked before or if they recently made some changes to the endpoints.
Perhaps a solution to the problem could be to pass a flag indicating that you want to send batch with templates and change the 'email/batch' string depending on the value of that flag.
Hi,
Not sure if this has been covered already, but thought I'd raise it anyway.
I'm using version 0.1.6 of the application, and am encountering an error that I was hoping someone would be able to provide me some advice on how to resolve.
On line 105 of models.py, the following code:
timestamp, tz = resp["SubmittedAt"].rsplit("+", 1)
generates a "need more than 1 value to unpack" error.
After a bit of investigation, I've figured out that the error is being thrown because the following call:
resp["SubmittedAt"]
is returning the timestamp from my system in the following format:
'2012-09-24T00:19:16.5390153-04:00'
However, postmark expects it to return a timestamp and a timezone separated with a "+" sign in a format similar to this:
26-FEB-09 11.36.25.390713 AM +13:00
Is there a relatively straight forward way to overcome this issue without modifying the code base itself?
thanks,
Mark
we always get this error but the email was successful.
lib.postmark.core.PMMailUnprocessableEntityException: 'Unprocessable Entity: Received valid, but incompatible JSON input.'
this is the sample output when I printed after self.to_json_message was executed.
{'From': '[email protected]', 'HtmlBody': 'Reports Sent (v4): 1', 'ReplyTo': '[email protected]', 'TextBody': 'Reports Sent (v4): 1', 'To': ['[email protected]', '[email protected]', '[email protected]'], 'Subject': 'Reports Sent (v4): 1'}
hope you can help.. thanks.
Django 1.11 made a change to the way text/* files are attached to a message; now it will try and decode the content into utf-8, which will bomb when this library attempts to b64encode it.
There should be a check to see if the content is unicode and then encode it to a string before b64'ing.
Hello!
I have a suggestion to improve the compatibility with pep8.
As you look at this?
I will present code in pull request.
Postmark API supports to set a MessageStream which the e-mail must be sent througth.
A use case is to allow users that send only transactional e-mail use the MessageStream dedicated for it.
Python-postmark should provide a "message_stream" string parameter that allows to set which MessageStream to use.
I have a bunch of hard bounced
emails in my postmark admin. I am not able to retrieve those using your PMBounceManager.get_all()
api.
Let me reproduce the issue :
from django.conf import settings
from postmark import PMMail, PMBounceManager
mailer = PMMail(subject="test", sender=settings.EMAIL_HOST_USER, to="[email protected]", tag="test", text_body="test")
mailer.send()
The email [email protected]
is invalid and get hard bounced like many other and it is shown in my postmark dashboard.
Although when I do :
manager = PMBounceManager()
manager.get_all()
The response is : {u'TotalCount': 0, u'Bounces': []}
I tried using the REST API from postmark directly at the same time and it works !!
Here is what I did with the REST API:
import requests
url = "https://api.postmarkapp.com/bounces?type=HardBounce&inactive=true&count=25&offset=0"
headers = {'X-Postmark-Server-Token': settings.POSTMARK_API_KEY, "Accept":"application/json", "Content-Type":"application/json"}
response = requests.get(url=url, headers=headers)
So now, print response.json()
gives me this :
{u'TotalCount': 19, u'Bounces': [{u'BouncedAt': u'2014-02-28T01:18:52.4828241- 05:00', u'Name': u'Hard bounce', u'Su.......
Is there anything I am missing ?
Without setup.py (and registration at http://pypi.python.org/#) it is quite annoying to install postmark in an automated fashion.
Looking at the code, it seems that if we directly use the PMMail object, we can get access to the MessageID of the resulting message.
However, when you use the PMEmailMessage.send, then there is no way of accessing the PMEmailMessage, because the code doesn't populate the MessageId back on this object.
thoughts?
Do you happen to know if python-postmark will be affected by the upcoming TLS changes Postmark is making to their API? From what I can tell, nothing in python-postmark should be affected, but I wanted to get a sanity check on that.
Thanks much!!
http://developer.postmarkapp.com/developer-opens.html
Working on a PR at the moment.
Hi,
I would like to enquire how the API deals with sending out emails with special characters inside the attributes. For example, currently I'm trying to send out an email whereby using the PMMail Object, I'm passing in this unicode value "u'\u7f2a\u5efa\u5175'" into the to attribute of the PMMail object. The value is supposed to be chinese characters. I sent the object to my own email and received the message with the chinese characters displayed, however I also get this error:
"An unknown error occured: 'ascii' codec can't decode byte 0xe7 in position 7: ordinal not in range(128)"
I tried changing a bit of the code for core.py on line 449
Original:
jsontxt = result.read().decode()
Edited:
jsontxt = result.read().decode('utf8')
The email sends out and gives me the chinese characters and also there is no error displayed.
What do you think?
Hi! In #89 , _send
was changed to return a tuple, and send_messages
was updated to expect a tuple.
However: looking at https://github.com/themartorana/python-postmark/pull/89/files#diff-0a79263ddca0f892c07ae4bdfe5201366d5e7dd9b0fc7d23be8937a1b9dce1edR142 we see that there are still cases where the _send
method returns a single boolean instead of a tuple of a boolean together with a list of messages. This then causes a TypeError in send_messages
.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.