OPDATERING 29. maj 2019: Dette program virker ikke længere. Prøv dette i stedet.
Der er mange, der har fået den idé, automatisk at videresende beskeder i E-boks til en anden mailadresse eller gemme dem på computeren. Videresendelse kan også gøres i E-boks selv, men kun manuelt og en besked ad gangen. Her er nogle projekter:
- MinEBoks og MinBoks af Lars Pehrsson: Windows Service og program
- E-boks-mailer by Christian Panton: Python-program, men dur ikke længere pga. ændringer i E-boks
- Net-Eboks by Dmitry Karasik: Perl-program
- Postboks af Ole Gam: Til Mac
Jeg kan kun finde ud af Python, og ved hvordan jeg sætter et job op på min webserver, der kan gøre Python-programmer regelmæssigt (det skulle jeg nemlig bruge til https://wallnot.dk).
Så – med kæmpe hjælp fra koden til Net-Eboks af Dmitry Karasik – har jeg skrevet et Python-program, der videresender nye beskeder i E-boks til min mail.
Programmet fungerer, men det er ikke gennemtestet, og tager ikke højde for fejl, fx. at brugeren indtaster forkerte oplysninger i programmet. Så det er nok en god idé også at logge ind på E-boks en gang imellem og lige se at alt bliver hentet og videresendt.
Du er velkommen til at bruge programmet, videreudvikle, og hvad du ellers kan finde på.
# -*- coding: utf-8 -*- # Author: Morten Helmstedt. E-mail: helmstedt@gmail.com. # Based on https://github.com/dk/Net-Eboks perl API for eboks.dk by Dmitry Karasik. Thanks! """ This program logs on to e-boks.dk and takes new messages and sends them to an e-mail. It requires mobile app login for e-boks (see http://www.e-boks.dk/help.aspx?pageid=db5a89a1-8530-418a-90e9-ff7f0713784a for how to create). It also requires access to a secure (SSL) SMTP server and mail account for sending e-mails. """ # Necessary modules from datetime import datetime # Current date and time import requests # Communicating with E-boks import hashlib # Hash configuration for challenge/logon import xml.etree.ElementTree as ET # Parse E-boks XML responses import smtplib # Sending e-mails from email.mime.multipart import MIMEMultipart # Creating multipart e-mails from email.mime.text import MIMEText # Attaching text to e-mails from email.mime.application import MIMEApplication # Attaching pdf to e-mails from email.mime.image import MIMEImage # Attaching images to e-mails from email.utils import formataddr # Used for correct encoding of senders with special characters in name (e.g. Københavns Kommune) import chardet # Text message character set detection import time # Pause between e-mails sent # Configuration data data = { 'emailserver': '', # Your mail server hostname: host.server.dk 'emailserverport': , # Mail server port, e.g. 465 'emailusername': '', # Sender mail account username 'emailpassword': '', # Sender mail account password 'emailfrom': '', # Sender e-mail, e.g. trump@usa.gov 'emailto': '', # Recipient e-mail, e.g. hillary@clinton.net 'cpr': '', # CPR number (no hyphens), e.g. 1234567890 'password': '', # E-boks mobile account password 'activation': '', # E-boks mobile account activation code 'numberofmessagesperfolder': '10', # Number of messages to request (10 is usually enough) 'unreadstatusvalue': "true", # Normally "true". If "false" also read messages are sent 'unreadmorethan': 0, # Normally 0, only unread messages are sent. If -1 all messages are sent 'sendemails': True, # If True, e-mails are sent, if False, they are not 'country': 'DK', 'type': 'P', 'deviceid': 'python-e-boks-000000000000', 'datetime': '', 'root': 'rest.e-boks.dk', 'nonce': '', 'sessionid': '', 'response': '3a1a51f235a8bd6bbc29b2caef986a1aeb77018d60ffdad9c5e31117e7b6ead3', 'uid': '', 'uname': '', 'challenge': '' } # Gets current date and time for E-boks challenge now = datetime.now() data['datetime'] = datetime.strftime(now, '%Y-%m-%d %H:%M:%SZ') # Hashes parts of configuration data and sets challenge value to authenticate with E-boks hashstring = data['activation']+":"+data['deviceid']+":"+data['type']+":"+data['cpr']+":"+data['country']+":"+data['password']+":"+data['datetime'] hashstringcoded = hashstring.encode('utf-8') data['challenge'] = hashlib.sha256(hashstringcoded).hexdigest().encode('utf-8') data['challenge'] = hashlib.sha256(data['challenge']).hexdigest() # These functions are used to create sessionid, nonce and authstring values for communicating # with E-boks throughout the program def sessionid(authenticate): sessionstart = authenticate.find('sessionid="')+len('sessionid="') sessionend = authenticate.find('"', sessionstart) data['sessionid'] = authenticate[sessionstart:sessionend] def nonce(authenticate): noncestart = authenticate.find('nonce="')+len('nonce="') nonceend = authenticate.find('"', noncestart) data['nonce'] = authenticate[noncestart:nonceend] def createauthstring(): authstr = 'deviceid="' + data['deviceid'] + '",nonce="' + data['nonce'] + ',sessionid="' + data['sessionid'] + '",response="' + data['response'] + '"' return authstr # Logon to mail server server = smtplib.SMTP_SSL(data['emailserver'], data['emailserverport']) server.login(data['emailusername'], data['emailpassword']) # First logon to e-boks url = "https://" + data['root'] + "/mobile/1/xml.svc/en-gb/session" content = '<Logon xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:eboks:mobile:1.0.0"><User identity="' + data['cpr'] + '" identityType="' + data['type'] + '" nationality="' + data['country'] + '" pincode="' + data['password'] + '"/></Logon>' authstr = 'logon ' + 'deviceid="' + data['deviceid']+ '",' + 'datetime="' + data['datetime'] + '",' + 'challenge="' + data['challenge'] + '"' headers = { 'Content-Type': 'application/xml', 'Content-Length': str(len(content)), 'X-EBOKS-AUTHENTICATE': authstr, 'Accept': '*/*', 'Accept-Language': 'en-US', 'Accept-Encoding': 'gzip,deflate', 'Host': data['root'], } r = requests.put(url, headers=headers, data=content) authenticate = r.headers['X-EBOKS-AUTHENTICATE'] nonce(authenticate) sessionid(authenticate) xml = ET.fromstring(r.text) # Saves username and user id data['uname'] = xml[0].attrib['name'] data['uid'] = xml[0].attrib['userId'] # Get folder data from e-boks url = 'https://' + data['root'] + '/mobile/1/xml.svc/en-gb/' + data['uid'] + '/0/mail/folders' authstr = createauthstring() headers = { 'X-EBOKS-AUTHENTICATE': authstr, 'Accept': '*/*', 'Accept-Language': 'en-US', 'Host': data['root'], } r = requests.get(url, headers=headers) authenticate = r.headers['X-EBOKS-AUTHENTICATE'] nonce(authenticate) xml = ET.fromstring(r.text) eboks_folders = xml # Get folder id's and numbers of unread messages for folder in eboks_folders: folderid = folder.attrib['id'] unread = folder.attrib['unread'] # Get messages ONLY if any unread messages in folder if int(unread) > data['unreadmorethan']: # Usually > 0. Can be changed to == 0 for debugging purposes # Get list of messages url = 'https://' + data['root'] + '/mobile/1/xml.svc/en-gb/' + data['uid'] + '/0/mail/folder/' + folderid authstr = createauthstring() headers = { 'X-EBOKS-AUTHENTICATE': authstr, 'Accept': '*/*', 'Accept-Language': 'en-US', 'Host': data['root'], } params = { 'skip': '0', 'take': data['numberofmessagesperfolder'] } r = requests.get(url, headers=headers, params=params) authenticate = r.headers['X-EBOKS-AUTHENTICATE'] nonce(authenticate) xml = ET.fromstring(r.text) eboks_messages = xml i = 0 max = int(params['take']) - 1 while i <= max: for child in eboks_messages: messageid = child[i].attrib['id'] subject = child[i].attrib['name'] sender = child[i][0].text unreadstatus = child[i].attrib['unread'] attachmentcount = child[i].attrib['attachmentsCount'] format = child[i].attrib['format'].lower() received = child[i].attrib['receivedDateTime'] i += 1 # Get only messages that are unread if unreadstatus == data['unreadstatusvalue']: # Usually true. Can be changed to false for debugging purposes # Start e-mail msg = MIMEMultipart() msg['From'] = formataddr((sender, data['emailfrom'])) msg['To'] = data['emailto'] msg['Subject'] = "E-boks: " + subject body = "" # Get message (marks it as read) url = 'https://' + data['root'] + '/mobile/1/xml.svc/en-gb/' + data['uid'] + '/0/mail/folder/' + folderid + '/message/' + messageid authstr = createauthstring() headers = { 'X-EBOKS-AUTHENTICATE': authstr, 'Accept': '*/*', 'Accept-Language': 'en-US', 'Host': data['root'], } r = requests.get(url, headers=headers) authenticate = r.headers['X-EBOKS-AUTHENTICATE'] nonce(authenticate) # Get primary message content url = 'https://' + data['root'] + '/mobile/1/xml.svc/en-gb/' + data['uid'] + '/0/mail/folder/' + folderid + '/message/' + messageid + '/content' authstr = createauthstring() headers = { 'X-EBOKS-AUTHENTICATE': authstr, 'Accept': '*/*', 'Accept-Language': 'en-US', 'Host': data['root'], } r = requests.get(url, headers=headers) authenticate = r.headers['X-EBOKS-AUTHENTICATE'] nonce(authenticate) # Attach primary message content to e-mail if format in ("txt","text","plain"): characterset = chardet.detect(r.content) r.encoding = characterset['encoding'] body = r.text msg.attach(MIMEText(body, 'plain')) elif format in ("html","htm"): characterset = chardet.detect(r.content) r.encoding = characterset['encoding'] body = r.text msg.attach(MIMEText(body, 'html')) elif format == "pdf": filename = "".join().rstrip() + "." + format part = MIMEApplication(r.content) part.add_header('Content-Disposition', 'attachment', filename = filename) msg.attach(part) elif format in ("gif","jpg","jpeg","tiff","tif","webp"): filename = "".join().rstrip() + "." + format part = MIMEImage(r.content) part.add_header('Content-Disposition', 'attachment', filename = filename) msg.attach(part) # Get attachment data if message has attachments if int(attachmentcount) > 0: url = 'https://' + data['root'] + '/mobile/1/xml.svc/en-gb/' + data['uid'] + '/0/mail/folder/' + folderid + '/message/' + messageid authstr = createauthstring() headers = { 'X-EBOKS-AUTHENTICATE': authstr, 'Accept': '*/*', 'Accept-Language': 'en-US', 'Host': data['root'], } r = requests.get(url, headers=headers) authenticate = r.headers['X-EBOKS-AUTHENTICATE'] nonce(authenticate) xml = ET.fromstring(r.text) eboks_attachment = xml # Gets if, name and format of attachment for child in eboks_attachment: for subtree in child: attachmentid = subtree.attrib['id'] attachmenttitle = subtree.attrib['name'] attachmentformat = subtree.attrib['format'] # Gets the actual attachment url = 'https://' + data['root'] + '/mobile/1/xml.svc/en-gb/' + data['uid'] + '/0/mail/folder/' + folderid + '/message/' + attachmentid + '/content' authstr = createauthstring() headers = { 'X-EBOKS-AUTHENTICATE': authstr, 'Accept': '*/*', 'Accept-Language': 'en-US', 'Host': data['root'], } r = requests.get(url, headers=headers) authenticate = r.headers['X-EBOKS-AUTHENTICATE'] nonce(authenticate) # Attach attachment to e-mail if attachmentformat in ("txt","text","html","htm","plain"): filename = "".join().rstrip() + "." + attachmentformat r.encoding = "utf-8" part = MIMEText(r.text) part.add_header('Content-Disposition', 'attachment', filename = filename) msg.attach(part) elif attachmentformat == "pdf": filename = "".join().rstrip() + "." + attachmentformat part = MIMEApplication(r.content) part.add_header('Content-Disposition', 'attachment', filename = filename) msg.attach(part) elif attachmentformat in ("gif","jpg","jpeg","tiff","tif","webp"): filename = "".join().rstrip() + "." + attachmentformat part = MIMEImage(r.content) part.add_header('Content-Disposition', 'attachment', filename = filename) msg.attach(part) # Send e-mail if data['sendemails'] == True: print("sending") msg.attach(MIMEText(body, 'plain')) server.sendmail(data['emailfrom'], data['emailto'], msg.as_string()) time.sleep(2)