创建 PDF 并使用烧瓶邮件作为附件发送

Posted

技术标签:

【中文标题】创建 PDF 并使用烧瓶邮件作为附件发送【英文标题】:Create a PDF and send as attachment with flask-mail 【发布时间】:2021-07-29 11:15:01 【问题描述】:

我正在尝试使用 pdf-kit 从 html 页面创建 PDF,然后将该 pdf 作为电子邮件的附件发送。

这是我创建 pdf 的代码,这似乎有效:

                html = render_template("office_report.html",role=role, name=name,owner=off,reps=reps,all_weekly=all_weekly,we=we,totals=totals,cog=cog,all_weekly_rpt=True,off_rpt=off_rpt,v=v,adonors=adonors,ae=ae,ov=ov,pay_total=pay_total)
                options = "enable-local-file-access": None
                try:

                    pdf=pdfkit.from_string(html,False,options=options)
                    files =  pdf
                except Exception as e:
                    print(e)
                    pdf='ERROR'

然后我尝试发送电子邮件,但不明白如何将 PDF 附加到电子邮件。

try:

                    msg = Message('Owner Report ', sender = ("Brand Drivers",BD), recipients = ['jesswholt@gmail.com',BD,comp])
                    msg.body = "Weekly Report" + str(we)
                    
                    with app.open_resource(files) as fp:
                        msg.attach("Owner Report", "invoice/pdf", fp.read())
                    mail.mail.send(msg)
                    print('sent')
                except Exception as e:
                    print(e)

这里是转换成 PDF 的 HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />

<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />

<title>Childhelp</title>

<meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' name='viewport' />
<meta name="viewport" content="width=device-width" />


</head>
<body>

            <div class="header">
                <h4 class="title">Office Report <br>owner.owner_name<br>owner.office_ID</h4>
                <p>WeekEnding: we.strftime('%m-%d-%Y')</p>
            </div>


                  <table  id="office_weekly" class="table table-hover table-striped">

                      <thead>
                        <th>Ambassador</th>
                        <th>Transactions</th>
                        <th>Total Payments</th>
                        <th>Items Sold</th>
                        <th>Hotlines</th>
                        <th>Bonuses</th>
                      <!--  <th>Total</th>-->
                      </thead>
                      <tbody>
                        % for r in reps %
                          <tr>
                            <td>
                              <strong>r.rep_name</strong><br>
                              r.rep_ID
                            </td>
                            % for w in all_weekly if w.rep == r.rep_ID %
                            <td>w.transactions</td>

                            <td>
                              Cash: $w.cash/100<br>
                              Check: $w.check/100<br>
                              Card: $w.card/100<br>
                              <strong>Total: $w.total/100</strong>
                            </td>
                            <td>
                              Sold: w.tot_itm<br>
                              Refunded: w.refunds<br>
                              Amount Refunded: "$%.2f" % (w.amount_refunded/100)<br>
                              Refund Dates w.dates_refunded

                            </td>
                            <td>
                              Active: w.subs<br>
                              Cancels: w.can
                            </td>
                            <td>"$%.2f" % (w.bonus | float)</td>

                            % else %
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td>Report Incomplete</td>
                          </tr>
                          % endfor %
                        % endfor %
                        <tr>
                          <td><hr></td>
                          <td><hr></td>
                          <td><hr></td>
                          <td><hr></td>
                          <td><hr></td>
                          <td><hr></td>
                        </tr>
                      </tbody>

                      <tbody>
                      <tr>
                        <th></th>
                      </tr>
                      <td>Office Sub Total:</td>
                      <td>totals.transactions

                      </td>
                      <td>
                        Cash: totals.cash<br>
                        Check: totals.check<br>
                        Card: totals.card<br>
                        Total: totals.sales<br>
                        Overrides: "$%.2f" % (ov | float)

                      </td>
                      <td>
                        Items: totals.t_items<br>
                        COG: "$%.2f" % (cog) per piece<br>
                        Total COG: "$%.2f" % (totals.total_cog)

                      </td>
                      <td>
                        Total Hotlines for Office:<br>
                        Active: totals.hotlines<br>
                        Canceled: totals.cancels<br>

                        Total Pay Hotlines: "$%.2f" % (totals.hotlines | float * 15)

                      </td>
                      <td>
                        Total Bonuses Paid: totals.bonus<br>

                        Items Refunded: totals.items_refunded<br>

                        Amount Refunded: totals.amount_refunded / 100

                      </td>
                      </tbody>
                      <tbody>
                        <tr>
                          <th> Line Items</th>
                        </tr>
                        <td></td>
                        <td></td>
                      <td><strong>Balance Carry: off_rpt.balance_carry</strong></td>

                      </tbody>
                      <tbody>
                        <td></td>
                        <td></td>
                      <td><strong>Deposit: off_rpt.deposit</strong></td>

                      </tbody>
                      <tbody>
                        <td></td>
                        <td></td>
                      <td><strong>Events: totals.events</strong></td>

                      </tbody>
                      <tbody>
                        <td></td>
                        <td></td>
                      <td><strong>Line Items:</strong></td>

                      <td>
                        Name: v.li1_n<br>
                        Amount: $v.li1_p<br>
                        Name: v.li2_n<br>
                        Amount: $v.li2_p<br>
                        Name: v.li3_n<br>
                        Amount: $v.li3_p<br>
                        Name: v.li4_n<br>
                        Amount: $v.li4_p
                      </td>
                      </tbody>

                      <tbody>
                        <td></td>
                        <td></td>
                        <td></td>
                        <td></td>
                      % if pay_total %
                        <td><strong>Owner Payout:</strong></td>
                        <td><strong>"$%.2f" % (pay_total | float)</strong></td>
                      % else %
                        <td><strong>Card Sales:</strong></td>
                        <td><strong>totals.card</strong></td>
                      % endif %
                      </tbody>

                      <tbody>
                        <td>
                          <h3>Hotline Signups</h3>
                        </td>
                      </tbody>
                      <thead>
                        <th>Donor Name</th>
                        <th>Ambassador</th>

                        <th>Signup Date</th>
                        <th>Canceled</th>

                      <!--  <th>Total</th>-->
                      </thead>
                      <tbody>
                        % for d in adonors %
                        <tr>
                          <td>d.donor_name</td>
                          % for x in reps if x.rep_ID == d.rep_ID %
                          <td>x.rep_name<br>x.rep_ID</td>
                          % endfor %

                          <td>d.monthly_start_date</td>
                          % if d.donor_status == False %
                            <td>d.monthly_stop_date</td>
                          % else %
                            <td style="color:green">Active</td>
                          % endif %
                        </tr>

                        % endfor %
                      </tbody>

                  </table>
                  <div class="col-md-18">

                  </div>




    </body>

    </html>

【问题讨论】:

【参考方案1】:

而不是这个:

with app.open_resource(files) as fp:
    msg.attach("Owner Report", "invoice/pdf", fp.read())

这样做:

msg.attach("Owner Report", "invoice/pdf", pdf)

pdf(或files)包含您的文件作为字节类型对象。所以你不需要使用open_resource 来读取文件,因为你已经有了你需要的数据。

【讨论】:

当我尝试这种方式时,它会发送一个空白附件? 可以列出pdfhtml的值吗? 是的,如果我返回 HTML,它会完美运行,如果我调用 print(pdf),它会在终端中打印 对不起,我的意思是如果您可以将这些变量的输出添加到问题中,以便可以重现空白附件问题。仅html 的输出可能就足够了。 我已将 HTML 添加到原始问题中

以上是关于创建 PDF 并使用烧瓶邮件作为附件发送的主要内容,如果未能解决你的问题,请参考以下文章

在批准报价、运行报告、生成 PDF 并发送带有 PDF 作为附件的电子邮件

如何在Django中将pdf作为电子邮件附件发送

无法使用烧瓶邮件python将附件添加到邮件

Cakephp 发送电子邮件,附件发送为 0 字节

有啥方法可以在烧瓶邮件中命名附加的 pdf 文件?

使用 FPDF 通过 PHP 发送 PDF 附件