如何防止Python在发送电子邮件时泄漏文件路径?

huangapple go评论73阅读模式
英文:

How to prevent python for giving away file path when sending email?

问题

这是我的Python邮件发送代码。我总是在发送邮件时使用绝对路径作为附件,但问题是附件的名称会包含完整的目录结构,例如附件的名称可能是home/user/mail/filename.xls。

这是我尝试的解决方法:我使用了os.chdir来切换工作目录,然后发送邮件,这个方法能够解决附件暴露目录结构的问题,但是发送邮件的时间增加了70秒以上。请问可能出了什么问题?

def send_mail(attribute):
    
    msg = MIMEMultipart()
    msg['From'] = send_from
    msg['To'] = send_to
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = subject

    part = MIMEBase('application', "octet-stream")
    part.set_payload(open(fatt, "rb").read())
    encoders.encode_base64(part)
    part.add_header('Content-Disposition', 'attachment; filename="' + fatt + '"')
    msg.attach(part)
    smtp = smtplib.SMTP(server, port)
    if isTls:
        smtp.starttls()
    smtp.login(username, password)
    smtp.sendmail(send_from, send_to, msg.as_string())
    smtp.quit()
英文:

Here is my python code for sending email. I always use an absolute path for attachment
when email was sent its always give away for dir structure for example
attachment will be named home/user/mail/filename.xls.

here is what I did
using os.chdir change to working dir then send an email which is working attachment no longer giving away dir structure but its taking more time for sending an email
like increasing more 70 secs. What could goes wrong ?

def send_mail(attribute):
    
    msg = MIMEMultipart()
    msg['From'] = send_from
    msg['To'] = send_to
    msg['Date'] = formatdate(localtime = True)
    msg['Subject'] = subject

    part = MIMEBase('application', "octet-stream")
    part.set_payload(open(fatt, "rb").read())
    encoders.encode_base64(part)
    part.add_header('Content-Disposition', 'attachment; filename="'+fatt+'"')
    msg.attach(part)
    smtp = smtplib.SMTP(server, port)
    if isTls:
        smtp.starttls()
    smtp.login(username,password)
    smtp.sendmail(send_from, send_to, msg.as_string())
    smtp.quit()

</details>


# 答案1
**得分**: 1

### 一种替代方案 - 路径拆分

您可以使用 `os.path.split` 将路径名拆分为 (head, tail) 对。Tail 部分将是所需获取的文件名。例如:

```python
&gt;&gt;&gt; os.path.split(&quot;/home/gavin/Desktop/gavin.jpeg&quot;)
(&#39;/home/gavin/Desktop&#39;, &#39;gavin.jpeg&#39;)
&gt;&gt;&gt; os.path.split(&quot;/home/gavin/Desktop/gavin.jpeg&quot;)[-1]
&#39;gavin.jpeg&#39;

您在代码中的更改将如下所示:

from os.path import split as path_split

def send_mail(attribute):    
    ...
    part.add_header(&#39;Content-Disposition&#39;, f&#39;attachment; filename=&quot;{path_split(fatt)[-1]}&quot;&#39;)
    ...

将路径拆分与 os.chdir 进行比较

通过 os.path.split 进行路径拆分实质上是一个字符串操作。在给定上下文中,有一些规则定义了数据存储的方式,它遵循这些规则以理解路径并提供一致的结果。

os.chdir API 更改了程序上下文中的当前工作目录。操作系统指令会检查文件在磁盘上的权限、有效性和存在性。与在内存中某个索引处拆分字符串相比,这是一个非常大的变化。

执行 chdir 将触发 sys.audit参考)。它执行了内部和第三方库添加的钩子。库添加钩子以维护状态的一致性,以及其他功能——我曾经使用它来使某个 CLI 工具的缓存失效。

您不需要更改目录来获取给定路径的文件名。根据您调用 os.chdir 的次数,触发的隐式操作数量会增加,从而增加执行时间。

英文:

An Alternate Solution - Path Splitting

You can use os.path.split to separate the pathname into (head, tail) pair. The tail would be the file name as intended to fetch. For eg:

&gt;&gt;&gt; os.path.split(&quot;/home/gavin/Desktop/gavin.jpeg&quot;)
(&#39;/home/gavin/Desktop&#39;, &#39;gavin.jpeg&#39;)
&gt;&gt;&gt; os.path.split(&quot;/home/gavin/Desktop/gavin.jpeg&quot;)[-1]
&#39;gavin.jpeg&#39;

Your changes in your code would look like:

from os.path import split as path_split

def send_mail(attribute):    
    ...
    part.add_header(&#39;Content-Disposition&#39;, f&#39;attachment; filename=&quot;{path_split(fatt)[-1]}&quot;&#39;)
    ...

Compare Path Splitting with os.chdir

Path Splitting via os.path.split is essentially a string manipulation operation. There are certain rules that define how data is stored in a given context, it follows those rules to make sense of the path and give a consistent result.

The os.chdir API changes the current working directory in the context of your program. The OS directive would check for permission, validity & existence of the file on disk. This is a very big change as compared to splitting a string at some index in memory.

An execution of chdir will trigger a sys.audit (ref). It executes hooks added by internal and third-party libraries. Libraries add hooks to maintain state consistency among other things - I've used this to invalidate caches for a certain CLI tool too.

You don't need to change the directory to fetch the file name of a given path. Depending on how many times you invoke os.chdir, the number of implicit actions it triggers is compounded, thereby increasing the execution time.

huangapple
  • 本文由 发表于 2023年6月13日 14:30:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76462187.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定