Base64 电子邮件附件未上传

Posted

技术标签:

【中文标题】Base64 电子邮件附件未上传【英文标题】:Base64 email attachments are not uploading 【发布时间】:2012-02-06 12:03:11 【问题描述】:

我正在使用以下脚本 http://stuporglue.org/recieve-e-mail-and-save-attachments-with-a-php-script/ 来处理发送给我的电子邮件,但是,如果用户从 mail 或 Outlook 或任何发送 base64 附件的电子邮件客户端发送电子邮件,它们似乎不会保存在数据库,电子邮件的正文也被跳过。

我想知道是否有人在代码中看到错误,因为我已经查看并没有看到任何突出的内容。

仔细观察会发现以下内容 Mail.app 像这样发送它的 base64。

    --Apple-Mail=_9E76B10A-4086-43B8-B835-78F184FA43FC
Content-Disposition: inline;
    filename=CV-IT.pdf
Content-Type: application/pdf;
    name="CV-IT.pdf"
Content-Transfer-Encoding: base64

JVBERi0xLjQKJcOkw7zDtsOfCjIgMCBvYmoKPDwvTGVuZ3RoIDMgMCBSL0ZpbHRlci9GbGF0ZURl
Y29kZT4+CnN0cmVhbQp4nM1aS4/jNgy+z6/wucCkFmXJNjAwkMwkBXrbdoAeip76Aopuge5l/34l
kpKol+NseygGq01sPSiS30eKynhSw+env4dxGN0ns5qTHpZJndbh06/DD18Nf9E79/fp96fL+xOM
ywmGeR5d+/7L8PVNDcoM77/9+DKqDV5G2J7Vy6i3Zx3aaXONwY/U2s31mPHj4t/hOGxWfHj27yd6
89P7t0/X96cPhRRqVqdlmM1EMsCgdJDBzwDZ8m424xbVadEooVsQ/IKuufgOr7HBZ9TpTWzp6t+l
rjcWGF7UiFP5uZWKCyjwTxV9nrBHNadCrSiLLUnY3Teo2Vlp1kvQfty58qokIdRKG1VnnMwLqi68
1iuv84btlZ/ehAT1Z9HCyKNL+U5mVKsVPuKkhOk0k5R6UMD2GaFwDm8dr2tsbDQRyMcLOYdis9jx
Qt+U+3vlIRM9cBszzkzUETstYvabf/DqXgr5Fe5ADVLqnz8+je6/z9nmvvvmaRyelev0cVDz6oCC
X/4cvq/906zujV3BeWlACXvohZzt/9R0nM1YJ721WiCd9+BgM3nH8j785ue4+uZGHogAQNfX9MK5
v1f+htDvAXry9CMWA7kYCGSCEnD0VgZAo246YRRswCMBdI6dGRkJrDymZAaCLOh93Wh1sqVuNLMg
Al5R4yb2MqsA96STHXVk8yd1+Plg2uwLmAhvsO3NwUwcQC0speZmQRG0eZwGvxruaIPiHa3Qk0qn
QvdG8iJ2gZVmfo3MKeadCyuS7hOVCaotDA6zsBacxXoXpxs3pGc4bR1wa836md7/6JtamQDlaAqn
T8v6n0nQm2A2fD55jTvrpM3PucKFEXueKALLuexRaT7sPticRoNFnRZ2lnHq2CI4C2/W4dDKWJkG
wCpmJp2wGEaYyftex0bTAg2F37PQOJZQSdKfAwMJt8qIZF972ebY5dj/TPgK1v3DDVaEdEs2vmSr
uK9qcnN2vRVGH2GMXU5Ti2dS0jCFdqEMIKB+4m1fvGWJsPH7G3a2bFQ/xGc2RNzYDT8SpdP7ROw4
V0gHmoE0CZ0H0jyErnovhM6TM6pHK3vBFLxAdbwAg60YUFHmA1A0HTDCG4cF1/3qVQi3HEjtDhwP
BCq8tqmv+6imNZuDBhJbY/TTo6e9Yimt4isNGcO6oavqdBXJKo4SLqu6aee0WHcgqHXbhyQZQ60h
A2yG8yVf30GKk1RSmmTWRZ4ZkGKucn8aJzUx/82yAdYKQ9+IbRMv3ErjCBErvJZUKDwkxcIlBSjh
VZXANWX0ghaopjeXK***sCQTKnvDC3YuekODuJcsbjmLFdO9e2nAAQVTeXNZI2IjK
lzZMfgp/yLNYqBAxcirAE2OoApaneMQC8vG/8u4r9DAl32PymNLwAeJS53Zw4Dz5BpggNvJ+LJ83
cV8BN/hQWrTQ1JgPeKjAAiHjarRjCrer9+kZ4QbkCgPImY1Rx/
xKzWTUqYLR72s9ElZMvobeo21seOQIz10egQrILR2rFPuE7uC5SDdhxHvrEheuTjOBa+W46N/Syw
FEy4fzYUYnx0vJdJYdNEv+SP93prSS27XFcbtywJolTJ7LcV27psAzbWZovda2CVjMyM+oxgBgth
+V5ks2Ucy0W5i3JX5zJKP32fRE/Dv8me9Cpp/N0Ql5g0JYXkTrdCqkA54gz7tqsjyvw8GuDwtI5Z
/SP1L83NXeuaG7D7yI0HAqUdaelxS/PyB+ffsG920fxFM2fdN3/u7TOyql2pBS0F8wfj1zQ04MST
oPRrG9sdFpvfrh6ILlGU9JyiwhMmIbkfHctNSAenMp3yF0gKEmwtPDfxSnv9OU01wyG7d/JvKxwJ+Iqf
X9iuCOOPLV9Q8/ajoxtIybOHq5Yu6W7d95RqT/ZP7V+fNHPlYPJ05cb8kowfLquOe/SOopkZ+Oft
RwpKCrjT0Wm+vXXtT0wT45/H/55cYZUZ9VXeEjV/9K15C21Got5JYmKWjP8GZZb2G5R4NDMwtda6
1NVM1hk3kE1G3rlPZKL2CeZ+Hdp

虽然 Gmail 是这样发送的。

Content-Type: application/pdf; name="CV-IT.pdf"
Content-Disposition: attachment; filename="CV-IT.pdf"
Content-Transfer-Encoding: base64
X-Attachment-Id: f_gx86pbon0

JVBERi0xLjQKJcOkw7zDtsOfCjIgMCBvYmoKPDwvTGVuZ3RoIDMgMCBSL0ZpbHRlci9GbGF0ZURl
Y29kZT4+CnN0cmVhbQp4nM1aS4/jNgy+z6/wucCkFmXJNjAwkMwkBXrbdoAeip76Aopuge5l/34l
kpKol+NseygGq01sPSiS30eKynhSw+env4dxGN0ns5qTHpZJndbh06/DD18Nf9E79/fp96fL+xOM
ywmGeR5d+/7L8PVNDcoM77/9+DKqDV5G2J7Vy6i3Zx3aaXONwY/U2s31mPHj4t/hOGxWfHj27yd6
89P7t0/X96cPhRRqVqdlmM1EMsCgdJDBzwDZ8m424xbVadEooVsQ/IKuufgOr7HBZ9TpTWzp6t+l
rjcWGF7UiFP5uZWKCyjwTxV9nrBHNadCrSiLLUnY3Teo2Vlp1kvQfty58qokIdRKG1VnnMwLqi68
1iuv84btlZ/ehAT1Z9HCyKNL+U5mVKsVPuKkhOk0k5R6UMD2GaFwDm8dr2tsbDQRyMcLOYdis9jx
Qt+U+3vlIRM9cBszzkzUETstYvabf/DqXgr5Fe5ADVLqnz8+je6/z9nmvvvmaRyelev0cVDz6oCC
X/4cvq/906zujV3BeWlACXvohZzt/9R0nM1YJ721WiCd9+BgM3nH8j785ue4+uZGHogAQNfX9MK5
v1f+htDvAXry9CMWA7kYCGSCEnD0VgZAo246YRRswCMBdI6dGRkJrDymZAaCLOh93Wh1sqVuNLMg
Al5R4yb2MqsA96STHXVk8yd1+Plg2uwLmAhvsO3NwUwcQC0speZmQRG0eZwGvxruaIPiHa3Qk0qn
QvdG8iJ2gZVmfo3MKeadCyuS7hOVCaotDA6zsBacxXoXpxs3pGc4bR1wa836md7/6JtamQDlaAqn
T8v6n0nQm2A2fD55jTvrpM3PucKFEXueKALLuexRaT7sPticRoNFnRZ2lnHq2CI4C2/W4dDKWJkG
wCpmJp2wGEaYyftex0bTAg2F37PQOJZQSdKfAwMJt8qIZF972ebY5dj/TPgK1v3DDVaEdEs2vmSr
uK9qcnN2vRVGH2GMXU5Ti2dS0jCFdqEMIKB+4m1fvGWJsPH7G3a2bFQ/xGc2RNzYDT8SpdP7ROw4
V0gHmoE0CZ0H0jyErnovhM6TM6pHK3vBFLxAdbwAg60YUFHmA1A0HTDCG4cF1/3qVQi3HEjtDhwP
BCq8tqmv+6imNZuDBhJbY/TTo6e9Yimt4isNGcO6oavqdBXJKo4SLqu6aee0WHcgqHXbhyQZQ60h
A2yG8yVf30GKk1RSmmTWRZ4ZkGKucn8aJzUx/82yAdYKQ9+IbRMv3ErjCBErvJZUKDwkxcIlBSjh
VZXANWX0ghaopjeXK***sCQTKnvDC3YuekODuJcsbjmLFdO9e2nAAQVTeXNZI2IjK
lzZMfgp/yLNYqBAxcirAE2OoApaneMQC8vG/8u4r9DAl32PymNLwAeJS53Zw4Dz5BpggNvJ+LJ83
cV8BN/hQWrTQ1JgPeKjAAiHjarRjCrer9+kZ4QbkCgPImY1Rx/
xKzWTUqYLR72s9ElZMvobeo21seOQIz10egQrILR2rFPuE7uC5SDdhxHvrEheuTjOBa+W46N/Syw
FEy4fzYUYnx0vJdJYdNEv+SP93prSS27XFcbtywJolTJ7LcV27psAzbWZovda2CVjMyM+oxgBgth
+V5ks2Ucy0W5i3JX5zJKP32fRE/Dv8me9Cpp/N0Ql5g0JYXkTrdCqkA54gz7tqsjyvw8GuDwtI5Z
/SP1L83NXeuaG7D7yI0HAqUdaelxS/PyB+ffsG920fxFM2fdN3/u7TOyql2pBS0F8wfj1zQ04MST
oPRrG9sdFpvfrh6ILlGU9JyiwhMmIbkfHctNSAenMp3yF0gKEmwtPDfxSnv9OU01wyG7d/JvKxwJ+Iqf
X9iuCOOPLV9Q8/ajoxtIybOHq5Yu6W7d95RqT/ZP7V+fNHPlYPJ05cb8kowfLquOe/SOopkZ+Oft
RwpKCrjT0Wm+vXXtT0wT45/H/55cYZUZ9VXeEjV/9K15C21Got5JYmKWjP8GZZb2G5R4NDMwtda6
1NVM1hk3kE1G3rlPZKL2CeZ+Hdp

gmail 附件保存而 mail.app 不保存。

【问题讨论】:

这里的问题显然是正则表达式。它们完全适合 Gmail 的格式,但不适合 Maill.app - 我不擅长正则表达式,我相信有人可以快速写一些东西来解决这个问题。 代码查找Content-Disposition: attachment,这显然不在 Mac 消息中。 【参考方案1】:

免责声明有问题的脚本有更多问题,我不会解决,下面的答案是为了快速解决手头的问题,同时希望能启发一些读者无法自己诊断问题。 /免责声明

有两个主要问题。

问题 1:拆分标题行

看看这些标题:

Content-Disposition: inline;
    filename=CV-IT.pdf
Content-Type: application/pdf;
    name="CV-IT.pdf"

Content-Type: application/pdf; name="CV-IT.pdf"
Content-Disposition: attachment; filename="CV-IT.pdf"

现在看看处理这些行的部分:

$info = split("\n",$parts[0]);
..
foreach($info as $line)

    if( preg_match("/Content-Type: (.*);/",$line,$matches) )
    
        $type = $matches[1];
    
    if( preg_match("/Content-Disposition: attachment; filename=\"(.*)\"/",
        $line,$matches) ) 
        $name = time() . "_" . $matches[1];
    
    ..

这会将标题分成几行,然后尝试匹配每一行。现在看看这两个标题。第二个(工作)有 2 行,完全匹配。

第一个(不工作)有 4 行(!)。这 4 行都不符合模式。

有无数种方法可以解决这个问题,我会选择一个又快又脏的单线笔。在之前添加这一行$info = split("\n",$parts[0]);

$parts[0] = preg_replace("/\r?\n\s+/"," ",$parts[0]);

它会通过查找后跟空格的换行符并将它们替换为一个空格,从而再次将拆分的标头转换为单行符。

问题 2:错误的模式

假设你应用了上面的修复,你有这个模式:

if( preg_match("/Content-Disposition: attachment; filename=\"(.*)\"/", ...

试图匹配这一行:

Content-Disposition: inline; filename=CV-IT.pdf

这里有两个问题:

问题 2a:内联/附件处置

该模式清楚地寻找“附件”一词,而该行显示“内联”。这是通过将attachment 替换为(attachment|inline) 来解决的,这表示替代方案。 (请注意,这也捕获了处置类型)

问题 2b:文件名双引号

该模式进一步查找filename="(.*)",而该行有一个不带引号的文件名。

这也不是什么大问题,如果你在"之后插入?,表示"是可选的,一切都会起作用。为了使其完美,您还必须确保. 与结尾" 不匹配(如果可用),因此将filename="(.*)" 替换为:

filename="?([^"]+)"?

其中[^"]+ 代表“除" 之外的任何东西”。

所以如果你改变这些行:

if( preg_match("/Content-Disposition: attachment; filename=\"(.*)\"/",
    $line,$matches) ) 
    $name = time() . "_" . $matches[1];

进入

if( preg_match('/Content-Disposition: (attachment|inline); filename="?([^"]*)"?/',
    $line,$matches) ) 
    $disposition = $matches[1];
    $name = time() . "_" . $matches[2];

它应该工作。 (请注意,我将模式更改为使用单引号,这样您就不必转义双引号,使内容清晰可见)

为了让这个脚本万无一失,您应该真正阅读适当的 RFC,看看在电子邮件标题中还有什么可以期待的。该脚本包含很多个假设。

【讨论】:

【参考方案2】:

问题是我的脚本不是在寻找内联内容,而是在寻找附加的内容。使用您附加文件的方式,它是内联的,因此

内容处置:内联; 文件名=CV-IT.pdf

如果你附上它,你会看到 内容处置:附件;文件名="CV-IT.pdf"

Content-Disposition 处理在我网站上脚本的第 54-64 行附近(链接在原始问题中)。

【讨论】:

【参考方案3】:

您似乎使用 preg_match 来获取第 166 行附近的邮件边界:

if (preg_match("/boundary=(.*boundary)$/",$line,$matches))
    $boundary = $matches[1];

您使用“/”字符作为正则表达式模式的分隔符,同时您的边界内容中有“/”。

所以这可能是您的代码不起作用的原因。

试试这个:

if (preg_match("boundary=(.*boundary)$",$line,$matches))
    $boundary = $matches[1];

【讨论】:

delimiter 仅适用于函数内引号中包含的字符串,如果内容有 delimiter char 则无关紧要。

以上是关于Base64 电子邮件附件未上传的主要内容,如果未能解决你的问题,请参考以下文章

TIdMessage - 附件在正文中显示为 Base64

在“nodejs”中使用“@sendgrid/mail”发送“base64”电子邮件“附件”时遇到问题

尽管在标头中发送了 base64,但附件无法识别

使用 Summernote 在 Laravel 中动态内联附件

UiPath Outlook邮件正文引用图片

在 MailMessage 中添加附件 base64 图像并在 html 正文中读取