通过 Gmail 发送电子邮件时应用 MSO 条件语句 API

Apply MSO conditional statements when sending email via Gmail API

我一直在使用 PHP 和 SwiftMailer 从 GSuite 帐户中的多个地址发送基本和更高级的 HTML 电子邮件。

我一直在通过 SMTP 发送这些电子邮件,并使用用户名和密码进行身份验证。这意味着我需要在所有帐户上启用 Gmail 的安全性较低的应用程序 (LSA)。据我所知,这些电子邮件在任何地方都显示良好 - 包括旧版本的 Outlook。

确保 LSA 设置保持打开状态并且我们在系统中拥有最新的帐户密码足以成为切换到 API 方法的理由。此外,我了解到 GSuite 帐户将不允许很快继续使用 LSA 方法——这本来应该发生的,但由于大流行而被推迟了。 https://9to5google.com/2019/12/17/g-suite-less-secure-apps/

我在 GSuite 中设置了一个邮件服务帐户。我没有使用 Swiftmailer 发送,而是选择 Gmail 'quickstart' PHP 库。这适用于基本的 HTML-formatted 电子邮件。当我说基本时,我说的是 header 和强标签以及字体颜色的一些内联 css。

下一个目标是发送更复杂的 HTML 电子邮件,其中包括更多样式、嵌入式远程图像和一些 MSO 条件语句。正在发送和传递电子邮件。当我查看电子邮件的 HTML 来源时,MSO 条件语句与包括 MS-specific 文档类型内容的其他标签一样似乎被删除了。此 HTML 正在使用 SwiftMailer 和 SMTP。

电子邮件在 Gmail、我的 Android 电子邮件应用程序和 Thunderbird 中看起来仍然很棒。它们在我尝试过的任何 Microsoft 中看起来都不正确 - 到目前为止的 Outlook 07 和 Win 10 Mail。我可能不再需要担心 Outlook 07,但如果 Win 10 Mail 不起作用,我担心的是 Outlook 365 等也不会。

如果我不能使用这些 MSO 条件语句,这可能意味着一个新的、更简单的电子邮件模板。然而,根据我读过的所有内容,这些条件是有效的。

下面是我一直试图发送的 HTML 电子邮件,但条件要么不起作用,要么正在被删除。我还包含了我用来发送消息的 Google 服务代码。

我尝试了在这里找到的各种编码选项、元标记和各种条件标记。如果 Google 不使用 SMTP,它会用 API 去除一些东西是没有意义的。也许关键是将 Swiftmailer 与 API 一起使用 - 我一直试图避免的另一个兔子洞。

代码

<?php               
    require_once 'Google/google-api-php-client/vendor/autoload.php';        
    
    $fromAddress = "validaccount@gsuite.com";
    
    $user_to_impersonate = $fromAddress;
    $sender = $user_to_impersonate;
                                                            
    putenv("GOOGLE_APPLICATION_CREDENTIALS=path_to_my_gmail_service_account_json_file");
    $client = new Google_Client();
    $client->useApplicationDefaultCredentials();
    $client->setSubject($sender);
    $client->setApplicationName("Quickstart");
    $client->setScopes(["https://www.googleapis.com/auth/gmail.compose"]);
    $service = new Google_Service_Gmail($client);       
    
    $fromName = "Sender Name";
    $sender = "validaccount@gsuite.com";
    $toAddress = "me@me.com";
    $toName = "My Name";
    $replyName = "Sender Name";
    $replyAddress = "validaccount@gsuite.com";
        
    $subject = "API Test";
      
    $strBody .= '<!DOCTYPE html>';
    $strBody .= '<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">';
    $strBody .= '<head>';
    $strBody .= '<meta http-equiv="content-type" content="text/html; charset=UTF-8">
        <meta name="viewport" content="width=device-width"> <!-- Forcing initial-scale shouldn\'t be necessary -->
        <meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- Use the latest (edge) version of IE rendering engine -->
        <meta name="x-apple-disable-message-reformatting">  <!-- Disable auto-scale in iOS 10 Mail entirely -->
        <meta name="format-detection" content="telephone=no,address=no,email=no,date=no,url=no"> <!-- Tell iOS not to automatically link certain text strings. -->
        <meta name="color-scheme" content="light">
        <meta name="supported-color-schemes" content="light">';     
    $strBody .= '<title></title>';  
    $strBody .= '</head>';
        
    $strBody .= "<body>";
    
    $strBody .= '<![if !mso]>  HTML meant for non-Outlook clients but it shows up everywhere  <![endif]>';
    
    $strBody .= '<![if mso]>  HTML meant for Outlook clients only but it shows up everywhere  <![endif]>';
    
    $strBody .= '<!--[if mso]><!-->  I read this might work better, but again it shows up everywhere  <!--<![endif]-->';
    
    $strBody .= '<!--[if (gte mso 9)|(IE)]> This had no affect either and shows up eveywhere <![endif]-->';
                
    $strBody .= "Everybody can see this";
    
    $strBody .= "</body></html>";
                                      
    $rawMsgStr = "From: =?utf-8?B?" . base64_encode($fromName) . "?=<{$sender}>\r\n";
    $rawMsgStr .= "To: =?utf-8?B?" . base64_encode($toName) . "?=<{$toAddress}>\r\n";
    $rawMsgStr .= "Reply-To: =?utf-8?B?" . base64_encode($replyName) . "?=<{$replyAddress}>\r\n";
    
    $rawMsgStr .= "Subject: =?utf-8?B?" . base64_encode($subject) . "?=\r\n";
    $rawMsgStr .= "MIME-Version: 1.0\r\n";
    //$rawMsgStr .= "Content-Language: en-US;\r\n";
    $rawMsgStr .= "Content-Type: text/html; charset=utf-8\r\n\r\r";
    //$rawMsgStr .= "Content-Transfer-Encoding: quoted-printable\r\n";
    //$rawMsgStr .= 'Content-Transfer-Encoding: base64' . "\r\n\r\n";
    //$rawMsgStr .= 'Content-Transfer-Encoding: 7bit\r\n\r\n';
    $rawMsgStr .= "{$strBody}\r\n";           
  
    // The message needs to be encoded in Base64URL
    $mime = rtrim(strtr(base64_encode($rawMsgStr), '+/', '-_'), '=');
    $msg = new Google_Service_Gmail_Message();
    $msg->setRaw($mime);
    //return $msg;        
    
    $service->users_messages->send($sender, $msg);        
    
    echo "Complete!";         
?>

结果源 (Outlook 2007)

<html lang="en"><head><meta http-equiv="content-type" content="text/html; charset=UTF-8">
        <meta name="viewport" content="width=device-width"> 
        <meta http-equiv="X-UA-Compatible" content="IE=edge"> 
        <meta name="x-apple-disable-message-reformatting">  
        <meta name="format-detection" content="telephone=no,address=no,email=no,date=no,url=no"> 
        <meta name="color-scheme" content="light">
        <meta name="supported-color-schemes" content="light"><title></title></head><body>  HTML meant for non-Outlook clients but it shows up everywhere    HTML meant for Outlook clients only but it shows up everywhere    I read this might work better, but again it shows up everywhere  Everybody can see this</body></html>

Gmail 中的结果 HTML(Thunderbird 非常相似)

Content-Type: multipart/alternative; boundary="000000000000dc4b5d05bf2b6835"

--000000000000dc4b5d05bf2b6835
Content-Type: text/plain; charset="UTF-8"

 HTML meant for non-Outlook clients but it shows up everywhere HTML meant
for Outlook clients only but it shows up everywhere I read this might work
better, but again it shows up everywhere Everybody can see this

--000000000000dc4b5d05bf2b6835
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable


<html lang=3D"en"><head><meta http-equiv=3D"content-type" content=3D"text/h=
tml; charset=3DUTF-8">
=09    <meta name=3D"viewport" content=3D"width=3Ddevice-width">=20
=09=09<meta http-equiv=3D"X-UA-Compatible" content=3D"IE=3Dedge">=20
=09=09<meta name=3D"x-apple-disable-message-reformatting"> =20
=09=09<meta name=3D"format-detection" content=3D"telephone=3Dno,address=3Dn=
o,email=3Dno,date=3Dno,url=3Dno">=20
=09=09<meta name=3D"color-scheme" content=3D"light">
=09=09<meta name=3D"supported-color-schemes" content=3D"light"><title></tit=
le></head><body>  HTML meant for non-Outlook clients but it shows up everyw=
here    HTML meant for Outlook clients only but it shows up everywhere    I=
 read this might work better, but again it shows up everywhere  Everybody c=
an see this</body></html>

--000000000000dc4b5d05bf2b6835--

好吧,我想我最终证实了这一点。 Gmail API 正在从 HTML 电子邮件中删除注释,并通过删除与 MSO 相关的内容来简化文档类型标签。这不仅仅是 MSO 条件,它是电子邮件正文中的任何 HTML 评论。所以,我想这是以下内容的重复,并且正如该线程中的 OP 最近发现的那样,这个问题没有得到解决,并且可能在 Google 的眼中是设计使然。

Why does the GMail API strip the doctype and comments from outgoing messages?

最后我设计了一个更基本的 HTML 模板,没有任何 MSO 条件来绕过限制。