125 |
126 | """ % (title, inclocation)
127 | return response
128 |
129 | def returnFooter():
130 | response = """
131 |
132 |
136 |
137 |
138 | """
139 | return response
140 |
141 | lastfolder = ""
142 | def printQuote():
143 | quotes = ['Come on, shut off that damn alarm and I promise I\'ll never violate you again.', 'I\'ve become romantically involved with a hologram. If that\'s possible.', 'Listen to me very carefully because I\'m only going to say this once. Coffee - black.', 'Computer, prepare to eject the warp core - authorization Torres omega five nine three!', 'The procedure is quite simple. I\'ll drill an opening into your skull percisely two milimeters in diameter and then use a neuralyte probe to extract a sample of your parietal lobe weighing approximately one gram']
144 | return choice(quotes)
145 |
146 | class DecodeError(Exception):
147 | pass
148 |
149 | def decode_string(string):
150 | for charset in ("utf-8", 'latin-1', 'iso-8859-1', 'us-ascii', 'windows-1252','us-ascii'):
151 | try:
152 | return cgi.escape(unicode(string, charset)).encode('ascii', 'xmlcharrefreplace')
153 | except Exception:
154 | continue
155 | raise DecodeError("Could not decode string")
156 |
157 | attCount = 0
158 | lastAttName = ""
159 | att_count = 0
160 | last_att_filename = ""
161 |
162 | def saveToMaildir(msg, mailFolder):
163 | global lastfolder
164 | global maildir
165 |
166 | mbox = mailbox.Maildir(maildir, factory=mailbox.MaildirMessage, create=True)
167 | folder = mbox.add_folder(mailFolder)
168 | folder.lock()
169 | try:
170 | message_key = folder.add(msg)
171 | folder.flush()
172 |
173 | maildir_message = folder.get_message(message_key)
174 | try:
175 | message_date_epoch = time.mktime(parsedate(decode_header(maildir_message.get("Date"))[0][0]))
176 | except TypeError as typeerror:
177 | message_date_epoch = time.mktime([2000, 1, 1, 1, 1, 1, 1, 1, 0])
178 | maildir_message.set_date(message_date_epoch)
179 | maildir_message.add_flag("s")
180 |
181 |
182 | finally:
183 | folder.unlock()
184 | folder.close()
185 | mbox.close()
186 |
187 | def saveMostRecentMailID(mail_id, email_address, folder, filename = "nopriv.txt"):
188 | match = False
189 | for line in fileinput.input(filename, inplace = 1):
190 | if line.split(":")[0] == folder and line.split(":")[1] == email_address and len(line) > 3:
191 | line = folder + ":" + email_address + ":" + str(mail_id)
192 | match = True
193 | if len(line) > 3 and line != "\n":
194 | print(line)
195 | fileinput.close()
196 | if match == False:
197 | with open(os.path.join(filename), 'a') as progress_file:
198 | progress_file.write(folder + ":" + email_address + ":" + str(mail_id))
199 | progress_file.close()
200 |
201 |
202 |
203 | def getLastMailID(folder, email_address, filename = "nopriv.txt"):
204 | if not os.path.exists(filename):
205 | with open(os.path.join(filename), 'w') as progress_file:
206 | progress_file.write(folder + ":" + email_address + ":1")
207 | progress_file.close()
208 | match = False
209 | with open(os.path.join(filename), 'r') as progress_file:
210 | for line in progress_file:
211 | if len(line) > 3:
212 | latest_mailid = line.split(":")[2]
213 | email_addres_from_file = line.split(":")[1]
214 | folder_name = line.split(":")[0]
215 | if folder_name == folder and email_addres_from_file == email_address:
216 | progress_file.close()
217 | return latest_mailid
218 | return 0
219 | progress_file.close()
220 |
221 |
222 | def get_messages_to_local_maildir(mailFolder, mail, startid = 1):
223 | global IMAPLOGIN
224 | mail.select(mailFolder, readonly=True)
225 | try:
226 | typ, mdata = mail.search(None, "ALL")
227 | except Exception as imaperror:
228 | print("Error in IMAP Query: %s." % imaperror)
229 | print("Does the imap folder \"%s\" exists?" % mailFolder)
230 | return
231 |
232 | total_messages_in_mailbox = len(mdata[0].split())
233 | last_mail_id = 0
234 | try:
235 | last_mail_id = mdata[0].split()[-1]
236 | except Exception:
237 | pass
238 | folder_most_recent_id = getLastMailID(mailFolder, IMAPLOGIN)
239 |
240 | if folder_most_recent_id > 2 and incremental_backup == True:
241 | if not int(folder_most_recent_id) == 1:
242 | startid = int(folder_most_recent_id) + 1
243 | if startid == 0:
244 | startid = 1
245 |
246 | for message_id in range(int(startid), int(total_messages_in_mailbox + 1)):
247 | result, data = mail.fetch(message_id , "(RFC822)")
248 | raw_email = data[0][1]
249 | print('Saving message %s.' % (message_id))
250 | maildir_folder = mailFolder.replace("/", ".")
251 | saveToMaildir(raw_email, maildir_folder)
252 | if incremental_backup == True:
253 | saveMostRecentMailID(message_id, IMAPLOGIN, mailFolder)
254 |
255 |
256 |
257 | def returnIndexPage():
258 | global IMAPFOLDER
259 | global IMAPLOGIN
260 | global IMAPSERVER
261 | global ssl
262 | global offline
263 | now = datetime.datetime.now()
264 | with open("index.html", "w") as indexFile:
265 | indexFile.write(returnHeader("Email Backup Overview Page"))
266 | indexFile.write("
\n")
267 | indexFile.write("
Folders
\n")
268 | indexFile.write(returnMenu("", index=True, vertical = True, activeItem="index"))
269 | indexFile.write("\n")
270 | indexFile.write("
\n")
271 | indexFile.write("
Information
\n")
272 | indexFile.write("
This is your email backup. You've made it with ")
273 | indexFile.write("NoPriv.py from Raymii.org.
\n")
275 | indexFile.write("On the right you have the folders you wanted to backup.\n")
276 | indexFile.write("Click one to get the overview of that folder.
\n")
277 | indexFile.write("
\n
\n
\n")
278 | indexFile.write("Here is the information you gave me:
\n")
279 | indexFile.write("IMAP Server: " + IMAPSERVER + "
\n")
280 | indexFile.write("Username: " + IMAPLOGIN + "
\n")
281 | indexFile.write("Date of backup: " + str(now) + "
\n")
282 | indexFile.write("Folders to backup:
\n
\n")
283 | for folder in IMAPFOLDER:
284 | indexFile.write("\t- " + folder + "
\n")
285 | indexFile.write("
\n")
286 | indexFile.write("
Available Folders:
")
287 | if not offline:
288 | indexFile.write(returnImapFolders(available=True, selected=False, html=True))
289 | if ssl:
290 | indexFile.write("And, you've got a good mail provider, they support SSL and your backup was made over SSL.
\n")
291 | else:
292 | indexFile.write("No encrption was used when getting the emails.
\n")
293 | indexFile.write("Thats all folks, have a nice day!\n")
294 | indexFile.write("
")
295 | indexFile.write(returnFooter())
296 | indexFile.close()
297 |
298 |
299 | def allFolders(IMAPFOLDER_ORIG, mail):
300 | response = []
301 | if len(IMAPFOLDER_ORIG) == 1 and IMAPFOLDER_ORIG[0] == "NoPriv_All":
302 | maillist = mail.list()
303 | for imapFolder in sorted(maillist[1]):
304 | imapFolder = re.sub(r"(?i)\(.*\)", "", imapFolder, flags=re.DOTALL)
305 | imapFolder = re.sub(r"(?i)\".\"", "", imapFolder, flags=re.DOTALL)
306 | imapFolder = re.sub(r"(?i)\"", "", imapFolder, flags=re.DOTALL)
307 | imapFolder = imapFolder.strip()
308 | response.append(imapFolder)
309 | else:
310 | response = IMAPFOLDER_ORIG
311 | return response
312 |
313 | def returnImapFolders(available=True, selected=True, html=False):
314 | response = ""
315 | if available:
316 | if not html:
317 | response += "Available IMAP4 folders:\n"
318 | maillist = mail.list()
319 | for ifo in sorted(maillist[1]):
320 | ifo = re.sub(r"(?i)\(.*\)", "", ifo, flags=re.DOTALL)
321 | ifo = re.sub(r"(?i)\".\"", "", ifo, flags=re.DOTALL)
322 | ifo = re.sub(r"(?i)\"", "", ifo, flags=re.DOTALL)
323 | if html:
324 | response += "- %s
\n" % ifo
325 | else:
326 | response += "- %s \n" % ifo
327 | response += "\n"
328 |
329 | if selected:
330 | if html:
331 | response += "Selected folders:
\n"
332 | else:
333 | response += "Selected folders:\n"
334 | for sfo in IMAPFOLDER:
335 | if html:
336 | response += "- %s
\n" % sfo
337 | else:
338 | response += "- %s \n" % sfo
339 | if html:
340 | response += "
\n"
341 | else:
342 | response += "\n"
343 |
344 | return response
345 |
346 |
347 | def returnMenu(folderImIn, inDate = False, index = False, vertical = False, activeItem = ""):
348 | global IMAPFOLDER
349 |
350 | folder_number = folderImIn.split('/')
351 | current_folder = folder_number
352 | folder_number = len(folder_number)
353 | dotdotslash = ""
354 |
355 | if vertical:
356 | response = '
'
357 | else:
358 | response = ''
359 |
360 | if not index:
361 | for _ in range(int(folder_number)):
362 | dotdotslash += "../"
363 | if inDate:
364 | dotdotslash += "../../"
365 | if index:
366 | response += "\t- Index
\n"
367 | else:
368 | response += "\t- Index
\n"
369 |
370 |
371 | for folder in IMAPFOLDER:
372 | if folder == activeItem:
373 | response += "\t- " + folder + "
\n"
374 | else:
375 | response += "\t- " + folder + "
\n"
376 |
377 | if not index:
378 | response += "\t- Back
\n"
379 | else:
380 | response += "\t- Raymii.org
\n"
381 | response += "\n
\n
\n"
382 |
383 | return response
384 |
385 | def remove(src):
386 | if os.path.exists(src):
387 | shutil.rmtree(src)
388 |
389 | def copy(src, dst):
390 | try:
391 | shutil.copytree(src, dst)
392 | except OSError as exc:
393 | if exc.errno == errno.ENOTDIR:
394 | shutil.copy(src, dst)
395 | elif exc.errno == errno.EEXIST:
396 | print("File %s already exists." % src)
397 | else: raise
398 |
399 | def move(src, dst):
400 | shutil.move(src, dst)
401 |
402 | def moveMailDir(maildir):
403 | print("Adding timestamp to Maildir.")
404 | now = datetime.datetime.now()
405 | maildirfilename = "Maildir." + str(now).replace("/", ".").replace(" ", ".").replace("-", ".").replace(":", ".")
406 | move(maildir, maildirfilename)
407 |
408 | def returnWelcome():
409 | print("##############################################")
410 | print("# NoPriv.py IMAP Email Backup by Raymii.org. #")
411 | if offline:
412 | print("# OFFLINE MODE ENABLED #")
413 | print("# version 6, released 17-11-2013. #")
414 | print("# https://raymii.org - NoPriv.py is GPLv3 #")
415 | print("##############################################")
416 | print("")
417 | print("Runtime Information:")
418 | print(sys.version)
419 | print("")
420 | print(printQuote())
421 | print("")
422 |
423 |
424 | def createOverviewPage(folder, pagenumber, amountOfItems = 50):
425 | if not os.path.exists(folder):
426 | os.makedirs(folder)
427 | overview_page_name = "email-report-" + str(pagenumber) + ".html"
428 | overview_file_path = os.path.join(folder, overview_page_name)
429 | with open(overview_file_path, "w") as overview_file:
430 | overview_file.write(returnHeader("Email backup page #" + str(pagenumber)))
431 | overview_file.write(returnMenu(folder, activeItem=folder))
432 | overview_file.write("")
433 | overview_file.write("")
434 | overview_file.write("")
435 | overview_file.write("# | ")
436 | overview_file.write("From | ")
437 | overview_file.write("To | ")
438 | overview_file.write("Subject | ")
439 | overview_file.write("Date | ")
440 | overview_file.write("
")
441 | overview_file.write("")
442 | overview_file.write("")
443 | overview_file.close()
444 |
445 |
446 |
447 | def addMailToOverviewPage(folder, pagenumber, mail_id, mail_from,
448 | mail_to, mail_subject, mail_date,
449 | mail_from_encoding = "utf-8", mail_to_encoding = "utf-8",
450 | mail_subject_encoding = "utf-8",
451 | attachment = False, emptyFolder = False):
452 | try:
453 | mail_subject = cgi.escape(unicode(mail_subject, mail_subject_encoding)).encode('ascii', 'xmlcharrefreplace')
454 | mail_to = cgi.escape(unicode(mail_to, mail_to_encoding)).encode('ascii', 'xmlcharrefreplace')
455 | mail_from = cgi.escape(unicode(mail_from, mail_from_encoding)).encode('ascii', 'xmlcharrefreplace')
456 | except Exception:
457 | mail_subject = decode_string(mail_subject)
458 | mail_to = decode_string(mail_to)
459 | mail_from = decode_string(mail_from)
460 |
461 | try:
462 | email_date = str(time.strftime("%d-%m-%Y %H:%m", email.utils.parsedate(mail_date)))
463 | attachment_folder_date = str(time.strftime("%Y/%m/", email.utils.parsedate(mail_date)))
464 | except TypeError:
465 | email_date = "Error in Date"
466 | attachment_folder_date = str("2000/1/")
467 |
468 | email_file_path = os.path.join(attachment_folder_date, str(mail_id), "index.html")
469 |
470 | overview_page_name = "email-report-" + str(pagenumber) + ".html"
471 | overview_file_path = os.path.join(folder, overview_page_name)
472 | with open(overview_file_path, "a") as overview_file:
473 | overview_file.write("\n\t\t")
474 | overview_file.write(str(mail_id))
475 | overview_file.write(" | \n\t\t")
476 | overview_file.write(mail_from.decode('string-escape'))
477 | overview_file.write(" | \n\t\t")
478 | overview_file.write(mail_to)
479 | overview_file.write(" | \n\t\t")
480 | if not emptyFolder:
481 | overview_file.write("")
482 | overview_file.write(mail_subject)
483 | if not emptyFolder:
484 | overview_file.write("")
485 | overview_file.write(" | \n\t\t")
486 | overview_file.write(str(mail_date))
487 | overview_file.write(" | \n\t
\n\t")
488 | overview_file.close()
489 |
490 | def finishOverviewPage(folder, pagenumber, previouspage, nextpage, total_messages_in_folder):
491 | overview_page_name = "email-report-" + str(pagenumber) + ".html"
492 | overview_file_path = os.path.join(folder, overview_page_name)
493 | with open(overview_file_path, "a") as overview_file:
494 | overview_file.write("\t\n")
495 | overview_file.write("\t | \n")
496 | overview_file.write("\t\t")
497 | if previouspage:
498 | overview_file.write("Previous page (#" + str(previouspage) + ")")
499 | else:
500 | overview_file.write("No previous page.")
501 | overview_file.write(" | \n")
502 |
503 | overview_file.write("\t\t")
504 | if nextpage:
505 | overview_file.write("Next page (#" + str(nextpage) + ")")
506 | else:
507 | overview_file.write("No more pages.")
508 |
509 | overview_file.write(" | \n")
510 | overview_file.write("\t\t")
511 | overview_file.write("Total items in folder: " + str(total_messages_in_folder))
512 | overview_file.write(" | \n")
513 |
514 | overview_file.write("\t | \n")
515 |
516 | overview_file.write("\t
")
517 | overview_file.write("\n
\n")
518 | overview_file.write(returnFooter())
519 | overview_file.close()
520 |
521 |
522 |
523 | def createMailPage(folder, mail_id, mail_for_page, current_page_number,
524 | mail_from, mail_to, mail_subject, mail_date,
525 | mail_has_attachment = False,
526 | mail_from_encoding = "utf-8",
527 | mail_to_encoding = "utf-8",
528 | mail_subject_encoding = "utf-8"):
529 |
530 | mail = mail_for_page
531 |
532 | try:
533 | mail_subject = cgi.escape(unicode(mail_subject, mail_subject_encoding)).encode('ascii', 'xmlcharrefreplace')
534 | mail_to = cgi.escape(unicode(mail_to, mail_to_encoding)).encode('ascii', 'xmlcharrefreplace')
535 | mail_from = cgi.escape(unicode(mail_from, mail_from_encoding)).encode('ascii', 'xmlcharrefreplace')
536 | except Exception:
537 | mail_subject = decode_string(mail_subject)
538 | mail_to = decode_string(mail_to)
539 | mail_from = decode_string(mail_from)
540 |
541 | mail_number = int(mail_id)
542 |
543 | print(("Processing mail %s from %s with subject %s.") % ( mail_id, mail_from, mail_subject))
544 |
545 | try:
546 | email_date = str(time.strftime("%d-%m-%Y %H:%m", email.utils.parsedate(mail_date)))
547 | attachment_folder_date = str(time.strftime("%Y/%m/", email.utils.parsedate(mail_date)))
548 | except TypeError:
549 | email_date = "Error in Date"
550 | attachment_folder_date = str("2000/1/")
551 |
552 | content_of_mail = {}
553 | content_of_mail['text'] = ""
554 | content_of_mail['html'] = ""
555 |
556 | for part in mail.walk():
557 | part_content_type = part.get_content_type()
558 | part_charset = part.get_charsets()
559 | if part_content_type == 'text/plain':
560 | part_decoded_contents = part.get_payload(decode=True)
561 | try:
562 | if part_charset[0]:
563 | content_of_mail['text'] += cgi.escape(unicode(str(part_decoded_contents), part_charset[0])).encode('ascii', 'xmlcharrefreplace')
564 | else:
565 | content_of_mail['text'] += cgi.escape(str(part_decoded_contents)).encode('ascii', 'xmlcharrefreplace')
566 | except Exception:
567 | try:
568 | content_of_mail['text'] += decode_string(part_decoded_contents)
569 | except DecodeError:
570 | content_of_mail['text'] += "Error decoding mail contents."
571 | print("Error decoding mail contents")
572 | continue
573 | elif part_content_type == 'text/html':
574 | part_decoded_contents = part.get_payload(decode=True)
575 | try:
576 | if part_charset[0]:
577 | content_of_mail['html'] += unicode(str(part_decoded_contents), part_charset[0]).encode('ascii', 'xmlcharrefreplace')
578 | else:
579 | content_of_mail['html'] += str(part_decoded_contents).encode('ascii', 'xmlcharrefreplace')
580 | except Exception:
581 | try:
582 | content_of_mail['html'] += decode_string(part_decoded_contents)
583 | except DecodeError:
584 | content_of_mail['html'] += "Error decoding mail contents."
585 | print("Error decoding mail contents")
586 |
587 | continue
588 |
589 |
590 |
591 | has_attachments = mail_has_attachment
592 | folder_path_1 = os.path.join(folder, attachment_folder_date, str(mail_number))
593 |
594 | mail_html_page = os.path.join(folder_path_1, "index.html")
595 | with open(mail_html_page, 'w') as mail_page:
596 | mail_page.write(returnHeader(mail_subject + " - NoPriv.py Email Backup by Raymii.org", "../../../inc/"))
597 | mail_page.write(returnMenu(folder_path_1, activeItem=folder))
598 | mail_page.write("\n")
599 | mail_page.write("\t\n")
600 | mail_page.write("\t\tFrom: | \n")
601 | mail_page.write("\t\t" + mail_from + " | \n")
602 | mail_page.write("\t
\n")
603 |
604 | mail_page.write("\t
\n")
605 | mail_page.write("\t\tTo: | \n")
606 | mail_page.write("\t\t" + mail_to + " | \n")
607 | mail_page.write("\t
\n")
608 |
609 | mail_page.write("\t
\n")
610 | mail_page.write("\t\tSubject: | \n")
611 | mail_page.write("\t\t" + mail_subject + " | \n")
612 | mail_page.write("\t
\n")
613 |
614 | mail_page.write("\t
\n")
615 | mail_page.write("\t\tDate: | \n")
616 | mail_page.write("\t\t" + mail_date + " | \n")
617 | mail_page.write("\t
\n")
618 |
619 | if has_attachments:
620 | mail_page.write("\t
\n")
621 | mail_page.write("\t\t | Click here to open the attachments. | \n")
622 | mail_page.write("\t
\n")
623 | mail_page.write("\t
| \n\t\tGo back | \n\t
\n")
624 |
625 | mail_page.write("
\n")
626 |
627 | if content_of_mail['text']:
628 | mail_page.write("
")
629 | strip_header = re.sub(r"(?i).*?.*?.*?", "", content_of_mail['text'], flags=re.DOTALL)
630 | strip_header = re.sub(r"(?i).*?", "", strip_header, flags=re.DOTALL)
631 | strip_header = re.sub(r"(?i)", "", strip_header, flags=re.DOTALL)
632 | strip_header = re.sub(r"(?i)POSITION: absolute;", "", strip_header, flags=re.DOTALL)
633 | strip_header = re.sub(r"(?i)TOP: .*?;", "", strip_header, flags=re.DOTALL)
634 | mail_page.write(decodestring(strip_header))
635 | mail_page.write("
\n")
636 |
637 |
638 | if content_of_mail['html']:
639 | strip_header = re.sub(r"(?i).*?.*?.*?", "", content_of_mail['html'], flags=re.DOTALL)
640 | strip_header = re.sub(r"(?i).*?", "", strip_header, flags=re.DOTALL)
641 | strip_header = re.sub(r"(?i)", "", strip_header, flags=re.DOTALL)
642 | strip_header = re.sub(r"(?i)POSITION: absolute;", "", strip_header, flags=re.DOTALL)
643 | strip_header = re.sub(r"(?i)TOP: .*?;", "", strip_header, flags=re.DOTALL)
644 | mail_page.write(decodestring(strip_header))
645 |
646 | mail_page.write("
Go back")
647 |
648 | mail_page.close()
649 |
650 | def save_mail_attachments_to_folders(mail_id, mail, local_folder, folder):
651 |
652 | global att_count
653 | global last_att_filename
654 | returnTrue = False
655 |
656 | try:
657 | att_date = str(time.strftime("%Y/%m/", email.utils.parsedate(mail['Date'])))
658 | except TypeError:
659 | att_date = str("2000/1/")
660 |
661 | if not os.path.exists(os.path.join(folder, att_date, str(mail_id), "attachments/")):
662 | os.makedirs(os.path.join(folder, att_date, str(mail_id), "attachments/"))
663 | else:
664 | remove(os.path.join(folder, att_date, str(mail_id), "attachments/"))
665 | os.makedirs(os.path.join(folder, att_date, str(mail_id), "attachments/"))
666 |
667 | with open(os.path.join(folder, att_date, str(mail_id), "attachments/index.html"), "w") as att_index_file:
668 | att_index_file.write(returnHeader("Attachments for mail: " + str(mail_id) + ".", "../../../../inc"))
669 | att_index_file.write(returnMenu("../../../../../", activeItem=folder))
670 | att_index_file.write("
Attachments for mail: " + str(mail_id) + "
\n")
671 | att_index_file.write("
\n")
672 | att_index_file.close()
673 |
674 | for part in mail.walk():
675 | if part.get_content_maintype() == 'multipart':
676 | continue
677 | if part.get('Content-Disposition') == None:
678 | continue
679 | decoded_filename = part.get_filename()
680 | filename_header = None
681 | try:
682 | filename_header = decode_header(part.get_filename())
683 | except (UnicodeEncodeError, UnicodeDecodeError):
684 | filename_header = None
685 |
686 | if filename_header:
687 | filename_header = filename_header[0][0]
688 | att_filename = re.sub(r'[^.a-zA-Z0-9 :;,\.\?]', "_", filename_header.replace(":", "").replace("/", "").replace("\\", ""))
689 | else:
690 | att_filename = re.sub(r'[^.a-zA-Z0-9 :;,\.\?]', "_", decoded_filename.replace(":", "").replace("/", "").replace("\\", ""))
691 |
692 | if last_att_filename == att_filename:
693 | att_filename = str(att_count) + "." + att_filename
694 |
695 | last_att_filename = att_filename
696 | att_count += 1
697 |
698 |
699 | att_path = os.path.join(folder, att_date, str(mail_id), "attachments", att_filename)
700 | att_dir = os.path.join(folder, att_date, str(mail_id), "attachments")
701 |
702 | att_locs = []
703 | with open(att_path, 'wb') as att_file:
704 | try:
705 | att_file.write(part.get_payload(decode=True))
706 | except Exception as e:
707 | att_file.write("Error writing attachment: " + str(e) + ".\n")
708 | print("Error writing attachment: " + str(e) + ".\n")
709 | return False
710 | att_file.close()
711 |
712 | with open(att_dir + "/index.html", "a") as att_dir_index:
713 | att_dir_index.write("- " + str(att_filename) + "
\n")
714 | att_dir_index.close()
715 | returnTrue = True
716 |
717 | with open(os.path.join(folder, att_date, str(mail_id), "attachments/index.html"), "a") as att_index_file:
718 | att_index_file.write("
")
719 | att_index_file.write(returnFooter())
720 | att_index_file.close()
721 | if returnTrue:
722 | return True
723 | else:
724 | return False
725 |
726 | def extract_date(email):
727 | date = email.get('Date')
728 | return parsedate(date)
729 |
730 | def return_sorted_email_list(maildir):
731 | sorted_mails = sorted(maildir, key=extract_date)
732 | sorted_mail_list = {}
733 | number = 0
734 | for mail in sorted_mails:
735 | sorted_mail_list[number] = mail
736 | number += 1
737 |
738 | return sorted_mail_list
739 |
740 |
741 | def backup_mails_to_html_from_local_maildir(folder):
742 | global maildir
743 | global messages_per_overview_page
744 | ## Maildir folders have dots, not slashes
745 | local_maildir_folder = folder.replace("/", ".")
746 | local_maildir = mailbox.Maildir(os.path.join(maildir), factory=None, create=True)
747 | try:
748 | maildir_folder = local_maildir.get_folder(local_maildir_folder)
749 | except mailbox.NoSuchMailboxError as e:
750 | print(("Error: Folder \"%s\" is probably empty or does not exists: %s.") % (folder, e))
751 | createOverviewPage(folder, 1, 0)
752 | addMailToOverviewPage(folder, 1, 1, "-", "-", "Error: Folder/mailbox does not exist or is empty", "01-01-1900", emptyFolder = True)
753 | finishOverviewPage(folder, 1, 0, 0, 0)
754 | return None
755 |
756 | ## Start with the first email
757 | mail_number = 1
758 | total_messages_in_folder = maildir_folder.__len__()
759 | try:
760 | number_of_overview_pages = float(total_messages_in_folder) / float(messages_per_overview_page)
761 | number_of_overview_pages = int(ceil(number_of_overview_pages))
762 | except Exception as error:
763 | print(error)
764 | raise
765 |
766 | sorted_maildir = return_sorted_email_list(maildir_folder)
767 | # We go through the mailbox in reverse
768 | start_mail_number = total_messages_in_folder
769 |
770 | ## Create the overview pages
771 | for number in reversed(range(number_of_overview_pages)):
772 | number += 1
773 | createOverviewPage(folder, number, messages_per_overview_page)
774 |
775 | current_page_number = 1
776 |
777 | ## Add the mail subject, from, to and date to the overview page
778 | run = 1
779 | for number in reversed(range(start_mail_number)):
780 | if (current_page_number * messages_per_overview_page) == mail_number:
781 | #if not current_page_number == 1:
782 | current_page_number += 1
783 | if not run == 1:
784 | mail_number += 1
785 | run += 1
786 | #key = maildir_folder.keys()[number]
787 |
788 | mail = sorted_maildir[number]
789 | mail_for_page = sorted_maildir[number]
790 | mail_subject = decode_header(mail.get('Subject'))[0][0]
791 | mail_subject_encoding = decode_header(mail.get('Subject'))[0][1]
792 | if not mail_subject_encoding:
793 | mail_subject_encoding = "utf-8"
794 |
795 | if not mail_subject:
796 | mail_subject = "(No Subject)"
797 |
798 | mail_from = email.utils.parseaddr(mail.get('From'))[1]
799 |
800 | mail_from_encoding = decode_header(mail.get('From'))[0][1]
801 | if not mail_from_encoding:
802 | mail_from_encoding = "utf-8"
803 |
804 | mail_to = email.utils.parseaddr(mail.get('To'))[1]
805 | mail_to_encoding = decode_header(mail.get('To'))[0][1]
806 | if not mail_to_encoding:
807 | mail_to_encoding = "utf-8"
808 |
809 | mail_date = decode_header(mail.get('Date'))[0][0]
810 |
811 | addMailToOverviewPage(folder, current_page_number, mail_number,
812 | mail_from, mail_to, mail_subject, mail_date,
813 | mail_from_encoding = mail_from_encoding,
814 | mail_to_encoding = mail_to_encoding,
815 | mail_subject_encoding = mail_subject_encoding,
816 | )
817 |
818 | mail_has_attachment = save_mail_attachments_to_folders(mail_number, mail_for_page, folder, folder)
819 |
820 | createMailPage(folder, mail_number, mail_for_page, current_page_number,
821 | mail_from, mail_to, mail_subject, mail_date,
822 | mail_has_attachment,
823 | mail_from_encoding = mail_from_encoding,
824 | mail_to_encoding = mail_to_encoding,
825 | mail_subject_encoding = mail_subject_encoding)
826 |
827 |
828 | ## Finish the overview page
829 | for number in reversed(range(number_of_overview_pages)):
830 | number += 1
831 | if number == 1 and number_of_overview_pages == 1:
832 | finishOverviewPage(folder, number, 0, 0, total_messages_in_folder)
833 | elif number == 1:
834 | finishOverviewPage(folder, number, 0, (number + 1), total_messages_in_folder)
835 | elif number == number_of_overview_pages:
836 | finishOverviewPage(folder, number, (number - 1), 0, total_messages_in_folder)
837 | else:
838 | finishOverviewPage(folder, number, (number - 1), (number + 1), total_messages_in_folder)
839 |
840 |
841 |
842 | returnWelcome()
843 |
844 | if not offline:
845 | mail = connectToImapMailbox(IMAPSERVER, IMAPLOGIN, IMAPPASSWORD)
846 | IMAPFOLDER = allFolders(IMAPFOLDER_ORIG, mail)
847 | print(returnImapFolders())
848 |
849 | returnIndexPage()
850 |
851 | if not offline:
852 | for folder in IMAPFOLDER:
853 | print(("Getting messages from server from folder: %s.") % folder)
854 | retries = 0
855 | if ssl:
856 | try:
857 | get_messages_to_local_maildir(folder, mail)
858 | except imaplib.IMAP4_SSL.abort:
859 | if retries < 5:
860 | print(("SSL Connection Abort. Trying again (#%i).") % retries)
861 | retries += 1
862 | mail = connectToImapMailbox(IMAPSERVER, IMAPLOGIN, IMAPPASSWORD)
863 | get_messages_to_local_maildir(folder, mail)
864 | else:
865 | print("SSL Connection gave more than 5 errors. Not trying again")
866 | else:
867 | try:
868 | get_messages_to_local_maildir(folder, mail)
869 | except imaplib.IMAP4.abort:
870 | if retries < 5:
871 | print(("Connection Abort. Trying again (#%i).") % retries)
872 | retries += 1
873 | mail = connectToImapMailbox(IMAPSERVER, IMAPLOGIN, IMAPPASSWORD)
874 | get_messages_to_local_maildir(folder, mail)
875 | else:
876 | print("Connection gave more than 5 errors. Not trying again")
877 |
878 | print(("Done with folder: %s.") % folder)
879 | print("\n")
880 |
881 |
882 | for folder in IMAPFOLDER:
883 | print(("Processing folder: %s.") % folder)
884 | remove(folder + "/inc")
885 | copy(inc_location, folder + "/inc/")
886 | backup_mails_to_html_from_local_maildir(folder)
887 | print(("Done with folder: %s.") % folder)
888 | print("\n")
889 |
890 | if not incremental_backup:
891 | moveMailDir(maildir)
892 |
--------------------------------------------------------------------------------