电子邮件主题中的动画图标

Animated icon in email subject

我知道 Data URIs,其中 base64 编码数据可以内联使用,例如图像。今天我收到一封实际上是垃圾邮件的邮件,其中的主题中有一个动画 (gif) 图标:

这里是单独的图标:

所以我唯一想到的就是数据 URI 以及 Gmail 是否允许在主题中插入某种表情符号。我看到了电子邮件的完整详细版本,并指向下图中的主题行:

所以 GIF 来自 =?UTF-8?B?876Urg==?= 编码字符串,类似于数据 URI 方案,但是我无法从中提取图标。这是元素 HTML 来源:

长话短说,有很多来自 https://mail.google.com/mail/e/XXX 的表情符号,其中 XXX 是十六进制数。它们无处记录,或者我找不到。如果那是关于数据 URI,那么如何将它们包含在 Gmail 的电子邮件主题中呢? (我将该电子邮件转发到雅虎电子邮件帐户,看到 [?] 而不是图标)如果不是,那么如何解析该编码字符串?

#简短描述:

它们在内部被称为 goomoji,它们似乎是一个非标准的 UTF-8 扩展。当 Gmail 遇到这些字符之一时,它会被相应的图标替换。我找不到关于它们的任何文档,但我能够对格式进行逆向工程。


#这些图标是什么?

这些图标实际上就是出现在“插入表情”面板下的图标。

虽然我在列表中没有看到 52E 图标,但还有其他几个遵循相同约定的图标。

请注意,还有一些图标的名称带有前缀,例如gtalk.03C 。我无法确定是否或如何以这种方式使用这些图标。


#这个Data URI是什么东西?

它实际上不是 Data URI, though it does share some similarities. It's actually a special syntax for encoding non-ASCII characters in email subjects, defined in RFC 2047。基本上,它是这样工作的。

=?charset?encoding?data?=

因此,在我们的示例字符串中,我们有以下数据。

=?UTF-8?B?876Urg==?=
  • charset = UTF-8
  • encoding = B(表示 base64)
  • data = 876Urg==

#那么它是怎样工作的?

我们知道不知何故,876Urg== 表示图标 52E,但是如何呢?

如果我们 base64 解码 876Urg==,我们得到 0xf3be94ae。这看起来像以下二进制文件:

11110011 10111110 10010100 10101110

这些位与一个 4 字节的 UTF-8 编码字符一致。

11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

所以相关位如下:

     011   111110   010100   101110

或对齐时:

00001111 11100101 00101110

在十六进制中,这些字节如下:

FE52E

如你所见,除了FE前缀这大概是为了区分goomoji图标和其他UTF-8字符,它匹配图标52E中的URL。一些测试证明这适用于其他图标。


#听起来工作量很大,有转换器吗?:

这当然可以编写脚本。我为测试创建了以下 Python 代码。这些函数可以将 base64 编码的字符串与 URL 中的短十六进制字符串相互转换。请注意,此代码是为 Python 3 编写的,与 Python 2 不兼容。

###转换函数:

import base64

def goomoji_decode(code):
    #Base64 decode.
    binary = base64.b64decode(code)
    #UTF-8 decode.
    decoded = binary.decode('utf8')
    #Get the UTF-8 value.
    value = ord(decoded)
    #Hex encode, trim the 'FE' prefix, and uppercase.
    return format(value, 'x')[2:].upper()

def goomoji_encode(code):
    #Add the 'FE' prefix and decode.
    value = int('FE' + code, 16)
    #Convert to UTF-8 character.
    encoded = chr(value)
    #Encode UTF-8 to binary.
    binary = bytearray(encoded, 'utf8')
    #Base64 encode return end return a UTF-8 string. 
    return base64.b64encode(binary).decode('utf-8')

###示例:

print(goomoji_decode('876Urg=='))
print(goomoji_encode('52E'))

###输出:

52E
876Urg==

当然,找到图标的 URL 只需要在 Gmail 中创建一个新草稿,插入您想要的图标,然后使用浏览器的 DOM 检查器。

如果您使用正确的十六进制代码点(例如 fe4f4 for 'pile of poo')并且如果它在主题行中正确编码 header,请将其设为 base64(请参阅@AlexanderOMara)或 quoted-printable (=?utf-8?Q?=F3=BE=93=B4?=),Gmail会自动解析并替换为相应的表情符号。

Here's a Gmail emoji list for copying and pasting into subject lines - 或电子邮件正文。将在收件箱中吸引更多注意力的动画表情符号放置在黄色背景上:

非常感谢 对带有 goomoji 标签的 HTML 图片进行了如此深入的研究!

我只想补充三点:

  • 垃圾邮件发送者和其他以前的营销人员开始在电子邮件主题行中使用许多表情符号(和其他生成图片的 Unicode 序列),而 gmail 不会转换为 HTML图片。在某些浏览器中,这些显示为粗体和彩色,这几乎和动画一样糟糕。浏览器 可以 也可以选择为这些设置动画,但我不知道是否有。这些 Unicode 序列被浏览器显示为 Unicode 文本,因此确切的外观(颜色与否,动画与否,...)取决于浏览器使用的文本渲染系统。给定 Unicode 表情符号的外观还取决于 Unicode 代码点序列中出现在它附近的任何 Unicode variation selectors and emoji modifiers。与基于图像的垃圾表情符号不同,这些序列可以作为 Unicode 文本从浏览器复制并粘贴到其他应用程序中。

  • 我希望阅读这个 Whosebug 问题的许多营销人员会拒绝。将这些序列包含在您的电子邮件主题行中是一个可怕的想法,它会立即玷污您和您的品牌作为垃圾邮件发送者的形象。这不值得 "attention" 您的电子邮件将收到。

  • 当然大家第一个想到的问题是:"how do I get rid of these things?"幸好有这个开源的Greasemonkey/Tampermonkey/Violentmonkey用户脚本:

Gmail Subject Line Emoji Roach Motel

此用户脚本消除了 HTML-image(感谢 的出色工作)和纯 Unicode 类型。

对于后一种类型,用户脚本包含一个正则表达式,旨在捕获可能被营销人员滥用的 Unicode 序列。正则表达式在 ES6 Javascript 中看起来像这样(用户脚本使用惊人的 ES6 Regex Transpiler 将其转换为广泛支持的 ES6 之前的正则表达式):

var re = /(\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F|[\u{2100}-\u{2BFF}\u{E000}-\u{F8FF}\u{1D000}-\u{1F5FF}\u{1F650}-\u{1FA6F}\u{F0000}-\u{FFFFF}\u{100000}-\u{10FFFF}])\s*/gu

// which includes the Unicode Emoji pattern from
//   https://github.com/tc39/proposal-regexp-unicode-property-escapes
// plus also these blocks frequently used for spammy emojis
// (see https://en.wikipedia.org/wiki/Unicode_block ):
//   U+2100..U+2BFF     Arrows, Dingbats, Box Drawing, ...
//   U+E000..U+F8FF     Private Use Area (gmail generates them for some emoji)
//   U+1D000..U+1F5FF   Musical Symbols, Playing Cards (sigh), Pictographs, ...
//   U+1F650..U+1FA6F   Ornamental Dingbats, Transport and Map symbols, ...
//   U+F0000..U+FFFFF   Supplementary Private Use Area-A
//   U+100000..U+10FFFF Supplementary Private Use Area-B
// plus any space AFTER the discovered emoji spam