当前位置: 首页 > 知识库问答 >
问题:

从电子邮件正文中删除其他换行符

花飞尘
2023-03-14

当发送电子邮件时,许多html" target="_blank">服务器会添加额外的换行符来限制每行的长度。

在PHP脚本中获取邮件时,如何恢复原来的换行符?

假设我发送以下内容:

Lorem ipsum Dolore incident in gulia ea sed quis sint voluptate quis laboratum ullamco Excepteur do adipiscing consecut ex in reprechter it officient in ad desrunt magna nulla dolor laboratum occur at reprechtr it aliquip dolor ea anim ea in veniam adipiscinging gulia tempor qui elit volupatte consectetur elit laborator elit labour minimum consecttur laborate anim incident una sunt sunt molit elit irure do杜洛雷·多洛雷·康奎特(英语:cillum dolore consequat in ea gupa ut velit sunt nulla in dolore voluptat dolore laboratory reprehender it dolore ut。
在威尼斯的乌特农(英语:ut non in veniam enim minim elit ad ut id ad ad eu voluptate dolor workers irure tempor mollit dolore exerciation eiusmod ea una una ullamco nostrud cillum nostrud laboratory commodo esse reprehendered out dise in an dolore ullamco pariator ament nulla除此之外,我们的官方fugiat eu used quis nisi fugiat dolor ea commodo ut sunt in consequat consectetur ut nullar pariatur est dolor dolore non ut occas Duis ut ex exexexexercise esse ullamco nullar incident commodo pariator dolore nostrud fugiat id dolor minimum not sint amet adipiscing occas enim non una irure sint aliquip nisi ut commodo minimum proident elit nullar out addolor Excepteur dolore Duis。

请注意,本文中只有一个换行符!

使用Thunderbird在接收端检查电子邮件的源代码,或通过PHP获取电子邮件正文,内容格式如下:

这是一个很好的例子,它说明了一个人在工作中所犯的错误但不包括最少的和最少的,但不包括欧盟自愿提供的劳工,除非欧盟官员拒绝提供劳工和商品 我们知道,即使货物不完全符合我们的要求,最少的货物也是可以的。

请注意,每行限制为一定长度,因此存在 16 个额外的换行符。这些额外的换行符是自动添加到导致我收到电子邮件的事件链中的某个地方的。

我希望我的电子邮件获取PHP脚本删除额外的换行符以恢复内容的原始两行格式。

我知道新的换行符不是由 PHP 脚本添加的,我知道它们来自哪里,我不知道的是我如何让我的 PHP 脚本删除这些换行符。

以下是用于获取电子邮件正文的代码:

$connection = imap_open(
    sprintf(
        '{%s:110/pop3}INBOX',
        Configure::read('Email.Inbox.host')
    ),
    Configure::read('Email.Inbox.email'),
    Configure::read('Email.Inbox.password')
);

$mailbox = imap_check($connection);
$messages = imap_fetch_overview($connection, '1:' . $mailbox->Nmsgs); 

foreach($messages as $message) {
    $content = imap_fetchbody($connection, $message->msgno, 1);
}

我尝试了什么?

我尝试使用< code>imap_body而不是< code>imap_fetchbody,因为前者不处理电子邮件正文。但是额外的换行符在此之前已经存在,并且与常规换行符无法区分。两者都由< code>\r\n组成。

我认为必须有一种方法可以做到这一点,因为 Thunderbird 以正确的格式显示收到的电子邮件,没有额外的 16 个换行符,尽管它们存在于显示消息的源代码中。因此,可能必须有一种方法可以从电子邮件中删除额外的 16 个换行符。

这是雷鸟的屏幕截图,顶部显示了电子邮件的源代码,底部显示了生成的纯文本显示。

共有1个答案

雍飞雨
2023-03-14

尽管这个问题很古老,但当我遇到这个完全相同的问题时,它是最热门的问题之一。正如Marc在评论中指出的,这确实与format=flowed有关。所以我深入到RFC 2646,找到了4.1节,生成格式=流:

由于软换行符是 SP CRLF 序列,因此生成代理通过在出现空格后插入 CRLF 来创建软换行符。

生成代理不应该在单词(不包含空格的可打印字符序列)中插入空白。如果遇到超过79个字符(但少于998个字符,即[SMTP]对行长度的限制)的单词,工程师应该按原样发送该单词,并超过79个字符的行长度限制。

因此,为了得到原来写的电子邮件,只需搜索所有的SP CRLF事件,并将其替换为空。然后,您可能还想取消空格填充,同时考虑引用的文本(以任意数量的< code >开头的行)

接收时,如果一行的第一个字符是空格,则逻辑上会删除它。这发生在引用管线测试之后,流动管线测试之前。

我自己厨房里的一份粗制滥造的PoC:

// I'm using fetchmime() because I want to be sure I'm getting the proper MIME type for the relevant section
$mimes = imap_fetchmime($connection, $message->msgno, $section);

// I don't want to store all headers in an array since I just want to know the Content-Type
// [ \t]* is probably not necessary but it's there in case of broken clients/servers
if(preg_match('/^[ \t]*Content-Type.*format=flowed\b/mi', $mimes)) {
    // First, let's undo space stuffing but don't touch stuffed lines with quotes
    $content = preg_replace('/^ +(?!>+ )/m', '', $content);

    // Then, remove flowed SP+(CR)LF sequences as well as any possible quotation marks that might appear after it to reform one long line of text
    $content = preg_replace('/( )\r?\n(>+ +)?/', '$1', $content);

    // Remove empty quoted lines at *the end of the string only*, keeping any such lines anywhere else as-is for readability
    $content = preg_replace('/(\r?\n>+\s*)+$/', '', $content);
}
// And finally trim the entire thing (regardless of formatting)
$content = trim($content);
// Or when outputting to browsers:
//$content = nl2br(trim($content));

对我来说,这在以下方面效果很好:

  • 简单的单行电子邮件
  • OP给出的lorem ipsum示例有2段
  • 一行后面跟着两行换行符和由两行组成的签名
  • 报价高达4级的电子邮件(可能超过4级,但我没有仔细检查)
 类似资料:
  • 在本章中,我们将了解如何使用JavaMail API删除电子邮件。 删除消息涉及使用与消息关联的标志。 不同的状态有不同的标志,一些是系统定义的,一些是用户定义的。 预定义标志在内部类Flags.Flag中定义,如下所示: Flags.Flag.ANSWERED Flags.Flag.DELETED Flags.Flag.DRAFT Flags.Flag.FLAGGED Flags.Flag.RE

  • 问题内容: 我正在使用PHP 函数: 当我收到这封电子邮件时,它看起来像这样: 我期望这样的事情: 没有HTTP标头也可以正常工作。如何制作 新行 并仍使用“ Content- Type”声明? 问题答案: 您需要使用一个,因为您是。 它没有标题就可以工作,因为这样您的电子邮件将被解释为 纯文本 。如果您确实想使用,则应该使用,但那样会丢失任何标记。

  • 问题内容: 我有以下代码: 问题是 新的换行符 不起作用。 问题答案: 尝试代替 \ n和\ r \ n之间的区别 应当注意,这适用于电子邮件中的行退回。

  • 问题内容: 我有以下数据,需要将它们全部放在一行中。 我有这个: 我需要这个: 这些命令均无法完美运行。 他们中的大多数让数据像这样: 问题答案: 编辑: 如果此处发布的所有命令均不起作用,则除了换行符以外,您还有其他用途。可能文件中有DOS / Windows行尾(尽管我希望Perl解决方案即使在这种情况下也可以工作)? 尝试: 如果这不起作用,那么您将不得不更仔细地检查文件(例如,在十六进制编

  • 我正在尝试为每月订阅付款设置带区。到这里查看我下面的文档:stripe.com/docs/recipes/subscription-signup我必须解决的问题是弹出表单包含“电子邮件地址”字段,但根据我的应用程序需要,我的数据库中已经有了用户的电子邮件地址。所以我想从弹出表单中删除这个“电子邮件地址”字段。但正如我所注意到的,弹出表单是从条带库https://checkout.stripe.co

  • 问题内容: 如何以一种在Windows和Linux上都可以使用的方式替换Java字符串中的所有换行符(即,没有特定于操作系统的回车/换行/换行等问题)? 我试过了(注意readFileAsString是一个将文本文件读入String的函数): 但这似乎不起作用。 如何才能做到这一点? 问题答案: 你需要text将结果设置为: 这是必需的,因为字符串是不可变的-调用不会更改原始字符串,它会返回已更改