1
0
SongZihuan 2 жил өмнө
parent
commit
8ca0a98376

+ 33 - 0
mailbox/email.py

@@ -6,6 +6,18 @@ import datetime
 import calendar
 
 
+class HTML:
+    def __init__(self, body):
+        self.body = body
+        self.type = "text/html"
+
+
+class PLAIN:
+    def __init__(self, body):
+        self.body = body
+        self.type = "text/plain"
+
+
 class Mail:
     date_pattern = re.compile(
         r"[A-Za-z]+, "
@@ -85,6 +97,27 @@ class Mail:
             else:
                 return ""
 
+    @property
+    def body_list(self):
+        return self.__get_body_list(self.msg_data)
+
+    def __get_body_list(self, msg):
+        if msg.is_multipart():
+            res = []
+            for i in msg.get_payload():
+                son = self.__get_body_list(i)
+                if son is not None:
+                    res += son
+            return res
+        else:
+            msg_type = msg.get_content_type()
+            if msg_type == "text/plain":
+                return [PLAIN(msg.get_payload(decode=True).decode('utf-8'))]
+            elif msg_type == "text/html":
+                return [HTML(msg.get_payload(decode=True).decode('utf-8'))]
+            else:
+                return None
+
     def save_file(self, file_dir: str):
         return self.__get_files(self.msg_data, file_dir)
 

+ 3 - 0
templates/base.html

@@ -104,5 +104,8 @@
     </section>
 
     {% block content %} {% endblock %}
+
+    {% block javascript_foot %}
+    {% endblock %}
 </body>
 </html>

+ 51 - 0
templates/mailbox/mail.html

@@ -0,0 +1,51 @@
+{% extends "base.html" %}
+{% block title %} 邮件 {% endblock %}
+
+{% block content %}
+<div class="container text-start">
+    <h2> {{ mail.title }} </h2>
+    <div>
+        <span class="badge bg-danger"> {{ mail.date }} </span>
+        <span class="badge bg-success"> {{ mail.from_addr }} </span>
+    </div>
+
+    {% for i in html_id %}
+        <div class="alert alert-success mt-3">
+            <strong>Wow!</strong> 这里有一封HTML邮件。</a>。
+        </div>
+        <iframe class="col-12 my-2 viewer"
+                src="{{ url_for("mailbox.html_page", date=date, select=select, mail=mail_id, id=i) }}">
+            你的浏览器不支持查阅此邮件。
+        </iframe>
+    {% endfor %}
+
+    {% for i in plain %}
+        <div class="alert alert-info mt-3">
+            <strong>Hi!</strong> 这是一封普通邮件。</a>。
+        </div>
+        <p style="text-indent: 2rem;word-break:break-all;">
+            {{ i.body }}
+        </p>
+    {% endfor %}
+
+</div>
+
+{% endblock %}
+
+
+{% block javascript_foot %}
+    {{ super() }}
+    <script>
+        const ifr_list = document.getElementsByClassName('viewer');
+        for (let i = 0; i < ifr_list.length; ++i) {
+            ifr_list[i].onload = function () {
+                const ifr = ifr_list[i]
+                const oHeight = Math.max(ifr.contentWindow.document.documentElement.offsetHeight, ifr.contentWindow.document.body.offsetHeight);
+                const cHeight = Math.max(ifr.contentWindow.document.documentElement.clientHeight, ifr.contentWindow.document.body.clientHeight);
+                const height = Math.max(oHeight, cHeight);
+                ifr.style.height = height + 'px'
+            }
+        }
+      </script>
+
+{% endblock %}

+ 1 - 1
templates/mailbox/mailbox.html

@@ -47,7 +47,7 @@
                     </p>
 
                     <div class="text-end">
-                        <a class="card-link"> 查看 </a>
+                        <a class="card-link" href="{{ url_for("mailbox.mail_page", date=date, select=select, mail=i.num) }}" target="_blank"> 查看 </a>
                     </div>
                 </div>
             </div>

+ 57 - 3
web/mailbox.py

@@ -1,4 +1,4 @@
-from flask import Blueprint, render_template, request, flash
+from flask import Blueprint, render_template, request, flash, abort
 from flask_login import login_required, current_user
 from flask_wtf import FlaskForm
 from wtforms import DateField, SelectField, SubmitField
@@ -6,7 +6,7 @@ from wtforms.validators import DataRequired
 from time import strftime, strptime, mktime, localtime
 from typing import List
 
-from mailbox.email import Mail
+from mailbox.email import Mail, HTML, PLAIN
 from .page import get_page, get_max_page
 from .logger import Logger
 
@@ -64,7 +64,7 @@ def mail_list_page():
 
     if date:
         date_obj = strptime(date, "%Y-%m-%d")
-        mail_list, download = current_user.get_mail(select, strftime('%d-%b-%Y', date_obj))
+        mail_list, download = current_user.get_mail_list(select, strftime('%d-%b-%Y', date_obj))
         if mail_list is None and not download:
             flash("旧任务未完成,正在下载邮件,请稍后")
             mail_list = []
@@ -86,3 +86,57 @@ def mail_list_page():
                                select=select,
                                next_date=next_date,
                                last_date=last_date)
+
+
+def __get_mail() -> (Mail, str, str, int):
+    mail_id = request.args.get("mail", None, type=int)
+    date = request.args.get("date", None, type=str)
+    select = request.args.get("select", None, type=str)
+    if not mail_id or not date or not select:
+        abort(404)
+
+    date_obj = strftime('%d-%b-%Y', strptime(date, "%Y-%m-%d"))
+    mail: Mail = current_user.get_mail(date_obj, select, mail_id)
+    if not mail:
+        abort(404)
+
+    return mail, date, select, mail_id
+
+
+@mailbox.route("/html")
+@login_required
+def html_page():
+    html_id = request.args.get("id", 1, type=int)
+    mail, *_ = __get_mail()
+
+    count = 0
+    for i in mail.body_list:
+        count += 1
+        if type(i) is HTML:
+            if count == html_id:
+                return i.body
+    return abort(404)
+
+
+@mailbox.route("/mail")
+@login_required
+def mail_page():
+    mail, date, select, mail_id = __get_mail()
+
+    count = 0
+    html_id = []
+    plain = []
+    for i in mail.body_list:
+        count += 1
+        if type(i) is HTML:
+            html_id.append(count)
+        elif type(i) is PLAIN:
+            plain.append(i)
+
+    return render_template("mailbox/mail.html",
+                           date=date,
+                           select=select,
+                           mail_id=mail_id,
+                           mail=mail,
+                           html_id=html_id,
+                           plain=plain)

+ 9 - 1
web/user.py

@@ -1,5 +1,6 @@
 from sender.smtp import Sender
 from mailbox.imap import Imap
+from mailbox.email import Mail
 from .db import redis
 from .configure import conf
 
@@ -75,7 +76,7 @@ class User(UserMixin):
             finally:
                 redis.set(f"download:mutex:{self.username}", 0)
 
-    def get_mail(self, inbox: str, date: str):
+    def get_mail_list(self, inbox: str, date: str):
         imap = Imap(user=conf["IMAP_USERNAME"].format(self.username),
                     passwd=conf["IMAP_PASSWD"].format(self.passwd),
                     host=conf["IMAP_HOST"],
@@ -107,3 +108,10 @@ class User(UserMixin):
                     ssl=conf["IMAP_SSL"],
                     start_ssl=conf["IMAP_START_SSL"])
         return imap.list()
+
+    def get_mail(self, date, inbox, mail_id):
+        byte = redis.get(f"mailbox:{self.username}:{inbox}:{date}:{mail_id}")
+        if not byte:
+            return None
+        return Mail(str(mail_id), byte.encode("utf-8"))
+