Python3 - imaplib - decrypt using pem certificate - python

As part of a larger workflow, I've been supplied with an email and password, and with an .pfx-certificate and password for that certificate. I need to use those to download a specific e-mail (specifically, its attachment), so it can be processed in other scripts.
I've already managed to transform the .pfx-file into a .pem file. Using the code below, I can download the message:
import email
import imaplib
EMAIL = 'test#test.com'
PASSWORD = 'testpassword'
SERVER = "outlook.office365.com"
# Connect to the server and go to its inbox
mail = imaplib.IMAP4_SSL(SERVER, port=993)
mail.login(EMAIL, PASSWORD)
mail.select('inbox')
# Get the relevant mail ID
status, ids = mail.search(None, '(HEADER Subject "Testmessage_")')
mail_id = ids[0].split()[0]
# Fetch the mail, get the data, write the file
status, contents = mail.fetch(mail_id, '(RFC822)')
data = contents[0][1]
with open("outputfile.txt", "wb") as outputfile:
outputfile.write(data)
I can then decode outputfile.txt with OpenSSL with the following command:
openssl cms -decrypt -in outputfile.txt -inkey cert.pem > outputmessage.txt
I can confirm that in the outputmessage.txt-file, the contents of the attachment are visible, and with some workaround, usable in the rest of my Python-script.
However, this means working with multiple temporary files and (at least) three different commands (python - openssl - python again). I would like to do all of this in Python, so I don't have to create temporary files and can process the results right away in the following scripts.
Additionally, I'd prefer to use as few external dependencies as possible.
I've seen M2Crypto and cryptography mentioned, but I can't seem to get either package working on my machine (something with wheels?). Are there any other options?

Trivially,
import subprocess
# ...
subprocess.run(['openssl', 'cms', '-decrypt',
'-inkey', 'cert.pem', '-out', 'outputmessage.txt'],
input=data, check=True)
I don't have openssl cms locally but I'm guessing from the man page that it will read standard input if you don't pass in an -in option. If that's not true, maybe try something like -in, - or maybe replace - with /dev/stdin or whatever your platform offers.

Related

IMAP with python to download attachments

I have a instrument at work that emails me a file containing raw data, I can go into my email and download them easily enough but when I have multiple files (which it sends as multiple emails) it gets a bit tedious.
I'm looking at using python and imaplib to login to my email account, search for emails from a known email address within the past day or so and then download any attachments to a directory. So I thought a script might help here.
I've setup a gmail account and altered the settings so that I can connect using imap from a shell, however I'm lost as to where to go from here.
Could someone point me in the right direction as to what I need to do to make this happen.
Here is a repository that is forked off imaplib (made compatible with Python3.6, did not test other versions)
https://github.com/christianwengert/mail
The following snippet checks all unseen messages, then returns their attachments:
server = IMAPClient(imap, use_uid=True, ssl=993)
server.login(username, password)
server.select_folder('INBOX')
message_ids = server.search([b'NOT', b'SEEN']) # UNSEEN
messages = server.fetch(message_ids, data=['ENVELOPE', 'BODYSTRUCTURE', 'RFC822.SIZE'])
for mid, content in messages.items():
bodystructure = content[b'BODYSTRUCTURE']
text, attachments = walk_parts(bodystructure, msgid=mid, server=server)
HTH

Hide login credentials in Python script

I am using Python 2.7.3 and successfully passing my login credentials to an SMTP server to send me a text or email when an event trigger takes place. However, now I would like to store the SMTP server login and password in a separate file so that multiple scripts could use that information or so that I can share my script without having to remove my credentials each time.
I am using the great tutorial from Alex Le on sending an SMS via Python. But now I want to take the following segment and put it into another file that can be called by multiple scripts. This could be either just the username/password pair or the whole section.
server = smtplib.SMTP( "smtp.gmail.com", 587 )
server.starttls()
server.login( '<gmail_address>', '<gmail_password>' )
I would consider myself a pretty basic Python programmer. I don't mind doing some research, but I think I need help on what terms I should be looking for.
Get all the critical variables from .yml file:
import yaml
conf = yaml.load(open('conf/application.yml'))
email = conf['user']['email']
pwd = conf['user']['password']
server = smtplib.SMTP( "smtp.gmail.com", 587 ) # add these 2 to .yml as well
server.starttls()
server.login(email, pwd)
The application.yml will look similar to this:
user:
email: example#mail.com
password: yourpassword
This way, you will never see the actual credentials in the script.
In production environments what we usually do is make a seperate file and save it somewhere outside the project. Now do chmod 600, i.e. allow only root to access the file. Now in your code run read the file by running in the the superuser mode. Or you could also create a different user which can access the file and run the code using that user.
OR You could use environment variables in your system. You can set one by doing the following in bash shell
export KEY=some_value
And then in your Python code
os.environ.get('KEY')
Use a separate configuration file settings.py containing:
EMAIL = 'gmail address'
PASSWORD = 'gmail password'
As the configuration file is a Python file, you can import it from your actual code:
from . import settings
server = smtplib.SMTP( "smtp.gmail.com", 587 )
server.starttls()
server.login(settings.EMAIL, settings.PASSWORD)
This is similar to what projects such as Django use, which you can see here.
You would need to keep the settings.py file secret, so you would not add it to your revision control software and wouldn't make it publicly readable.

Add image from static files to Multipart Email in Django

I am trying to send a logo with the email and have it appear in the HTML part of the email. I am building my email like this:
mail_subject = _("Subject of email %s" %
self.get_company_display())
from_email = "test#test.com"
message = EmailMultiAlternatives(mail_subject, mail_txt, from_email,
['destination#email.com'])
message.attach_alternative(mail_html, 'text/html')
message.attach('logo.png', static('myapp/images/logo.png'))
message.send()
And in my mail template I have:
<img src="cid:logo.png">
I receive the email but the image doesn't appear in the email. In fact, the email does not appear to have the image as an attachment.
Working on Python 3.4, Django 1.8.4 and sending the mails through Postfix installed on the same machine Django is running.
The EmailMessage.attach method expects to be passed the content of the file not its path, what you are actually doing is attaching the string returned by static('myapp/images/logo.png') to the message.
Use EmailMessage.attach_file instead (EmailMessage reference).
The whole purpose of yagmail (I'm the developer) is to make it really easy to send emails, especially with HTML or attachment needs.
Please try the following code:
import yagmail
yag = yagmail.SMTP(from_add, password) # add host="" and port=
contents = ['See my attachment below', '/home/static/images/logo.png']
yag.send(contents = contents)
Notice the magic here: contents is a list, where an item equal to a file path will automatically be loaded, mimetype guessed, and attached.
There's a lot more magic involved, such as easy to embed images, passwordless scripts, usernameless scripts, easy aliases, smart defaults (notice I omitted the to and subject arguments?) and much more. I advise/encourage you to read its github page :-). Feel free to raise issues or add feature requests!
You can get yagmail by using pip to install it:
pip install yagmail # Python 2
pip3 install yagmail # Python 3

getting started with davlib.py

I want to write a script to connect and access a webdav server. I found out that there is a
/usr/local/lib/python2.7/dist-packages/davlib.py
But how to use it? There is no tutorial, no documentation and nothing to google. Anybody able to write a small hello world for it?
the test webdav server is on localhost:80/webdav and there is a davtest.txt file with the word dav inside.
$ cd <path_to_webdav>
$ ls
davtest.txt
$ cat davtest.txt
dav
I can read python, so if I could just connect and read that there is a file called davtest.txt or maybe even it's content I think I could get started working with the source. Not knowing how webDAV works and not knowing davlib.py both together is quite tough, though.
With webdav-lib I could solve that problem:
url = "davs://localhost:80/webdav/davtest.txt"
r = ResourceStorer(url)
result = r.downloadContent().read()
To do a simple get request using davlib
import davlib
import base64
host = 'myhost'
protocol = 'myprotocol'
username = 'myusername'
password = 'mypassword'
url = '{}://{}/{}'.format(protocol, host, some_file_path)
d = davlib.DAV(protocol=myprotocol, host=myhost)
auth_token = base64.encodestring('%s:%s' %(username, password)).strip()
header = {"Authenication": "Basic %s' %auth_token}
d.get(url,header)
Basic authentication is usable only on https. For more (dry) details on webDAV, see the RFC.
The most mature webDAV client library I've found is python-webdav-library

SVN Notifications via GMAIL SMTP

I have got SVN running on Ubuntu 11.04 32bit and now want notifications using my GMAIL account for every commit.
I've commited a few things but don't actually recieve the commit emails for them. There aren't any errors that are displayed and I have looked through the logs but haven't found much useful information as of yet.
I've read quite alot of posts regarding this and editing the following files below including what they contain now. I've tried using sendmail and postfix but have had no luck with them hence which is why I am using Google's mail server. It would be grateful if someone could point me in the right direction or an alternative approach.
The links I found and have used.
http://sadomovalex.blogspot.com/2009/12/use-gmail-smtp-server-for-post-commit.html
http://iffee.wordpress.com/2009/04/08/svn-commit-to-google-apps-email-notification/
post-commit.tmpl
REPOS="$1"
REV="$2"
/home/megaz/svn/repos/ya/hooks/mailer.py commit "$REPOS" \
"$REV" /home/megaz/svn/repos/ya/hooks/mailer.conf
mailer.conf
[general]
smtp_hostname = smtp.gmail.com:587
smtp_username = #mygmailaddress
smtp_password = #mygmailpassword
smtp_use_ssl = true
smtp_use_tls = 1
[defaults]
diff = /usr/bin/diff -u -L %(label_from)s -L %(label_to)s %(from)s %(to)s
commit_subject_prefix = [SVN-Commit]
propchange_subject_prefix =
lock_subject_prefix =
unlock_subject_prefix =
from_addr = #my from address
to_addr = #my to address
reply_to = #my replyto address
generate_diffs = none
show_nonmatching_paths = yes
[maps]
mailer.py
class SMTPOutput(MailedOutput):
def start(self, group, params):
MailedOutput.start(self, group, params)
self.buffer = StringIO()
self.write = self.buffer.write
self.write(self.mail_headers(group, params))
def finish(self):
server = smtplib.SMTP(self.cfg.general.smtp_hostname)
# 2009-12-13 asadomov: add ssl configuration (e.g. for gmail smtp server)
if self.cfg.is_set('general.smtp_use_ssl') and self.cfg.general.smtp_use_ssl.lower() == "true":
server.ehlo()
server.starttls()
server.ehlo()
if self.cfg.is_set('general.smtp_username'):
server.login(self.cfg.general.smtp_username,
self.cfg.general.smtp_password)
server.sendmail(self.from_addr, self.to_addrs, self.buffer.getvalue())
server.quit()
I see, you have not really read the instructions. The code you have copy/pasted needs to replace a snippet in a larger file which you haven't downloaded. Also, the file name of the post-commit script should not have the .templ suffix; that's what they use for inactive example / template files in the distribution.
Perhaps this explains why you couldn't get Sendmail to work, either. At this point I'd recommend to go back to that, as it's simpler.
rename your "post-commit.templ" to "post-commit"
make sure you give exec rights (such as 755) to "post-commit"

Categories