Устранение потерь при кодировании почтовых аттачей в base64
Как известно,
Прошло время, текст в электронных письмах давно уже не только английский, а стандарты кодирования текстовых файлов до сих пор используют только латинские буквы (плюс цифры и некоторые символы, такие как плюс, миную, слеш и так далее). Мне пришло в голову — а что если попробовать кодировать файлы всем полем допустимых символов. Сейчас, когда появились письма
Из всех вариантов кодирования, а их три (Base64, UUencode
Я же задался целью проверить, что же будет, если попробовать передать файл, где поле допустимых символов расширено до максимума. Сразу скажу — эксперимент удался. Можено эксперементально внедрять новый формат кодирования писем. Назовём его Bolk
Я написал небольшую программу на PHP, которая в качестве параметра использует имя файла, который нужно закодировать, а на выход выдаёт этот файл в формате понятном почтовому клиенту. Таким образом, если её запустить как «php -q 8qp.php somegif.gif > somename.eml» и открыть получившийся файл вашим почтовым клиентом, внутри вы должны увидеть свою картинку.
<?php
// Example 1. 8qp.php
// Written by Evgeny Stepanischev aka BOLK
$bound = 'BOLKNOTE.RU';
$mime = getimagesize($argv[1]);
$mime = $mime['mime'];
$str = file_get_contents($argv[1]);
$len = filesize($argv[1]);
echo <<<HEADER
Content-Type: multipart/mixed;
boundary="----{$bound}"
------{$bound}
Content-Type: $mime; name="{$argv[1]}"
Content-Disposition: attachment; filename="{$argv[1]}"
Content-Transfer-Encoding: quoted-printable
HEADER;
$np = array (0, 10, 13, 61);
for ($i = 0; $i<$len; $i++)
{
$code = ord($str{$i});
echo in_array($code, $np) ?
'='.strtoupper(str_pad(dechex($code), 2, '0', STR_PAD_LEFT)):
$str{$i};
}
echo "rn------{$bound}--";Для эксперимента я выбрал наугад две картинки. JPEG и GIF. И вот что получилось в итоге. «TheBAT!» — это наименование моего почтового клиента.
Случайный GIF: исходный размер — 33590, мой
Случайный JPEG: исходный размер — 28144, мой
В случае
Эксперименты на первом же попавшемся Sendmail показали, что,
Последняя беда поставила меня в тупик. Правда, ненадолго. Вспомнив, что большинство клиентов умеют открывать письма в формате EML я решил пойти на хитрость — прикрепить моё письмо как аттачмент другого, замаскировав моё письмо под обычный текст — Sendmail вряд ли проверяет аттачи глубже одного вхождения. А чтобы письмо максимально адекватно воспринималось почтовым клиентом, я дал ему disposition inline и убрал из него все служебные поля. Попробовал отправить — получилось. В TheBat видно только лишнее пустое поле — беда небольшая.
<?php
// Example 2. 8qp_next.php
// Written by Evgeny Stepanischev aka BOLK
$bound = '3D1E1C92aaBF00D';
$bound2 = '3D1E1C92xxBF00D';
$mime = getimagesize($argv[1]);
$mime = $mime['mime'];
$str = file_get_contents($argv[1]);
$len = filesize($argv[1]);
echo <<<HEADER
From: <mailbox@sample.com>
To: mailbox@sample.com
From: mailbox@sample.com
Content-Type: multipart/mixed;
boundary="----------{$bound2}"
------------{$bound2}
Content-Type: message/rfc822; name="1.eml"; charset=utf-8
Content-Disposition: inline; name="1.eml"
Content-Transfer-Encoding: 8bit
Content-Transfer-Encoding: 8bit
Content-Type: multipart/mixed;
boundary="----{$bound}"
------{$bound}
Content-Type: $mime; name="{$argv[1]}"; charset=utf-8
Content-Disposition: attachment; filename="{$argv[1]}"
Content-Transfer-Encoding: quoted-printable
HEADER;
$np = array (0, 10, 13, 61);
for ($i = 0; $i<$len; $i++)
{
$code = ord($str{$i});
echo in_array($code, $np) ?
'='.strtoupper(str_pad(dechex($code), 2, '0', STR_PAD_LEFT)):
$str{$i};
if ($i && ($i % 512) == 0) echo "=rn";
}
echo "rn------{$bound}--",
"rn------------{$bound2}--";Полный размер письма после такой двойной «упаковки» увеличивается незначительно. Кстати говоря, Opera 7.0 с таким письмом не справилась. Возможно, в силу старости — текущая версия этого пакета — 7.61b. Для интереса я отправил письмо на мои ящики на серверах Mail.ru и Gmail.com. Оба сервера вполне достойно справились с задачей, единственно, что Gmail не принимал письмо, пока я не указал charset как