Книга: Программирование на языке Ruby

18.2.6. Кодирование и декодирование вложений

18.2.6. Кодирование и декодирование вложений

Для вложения в почтовое сообщение или в сообщение, отправляемое в конференцию, файл обычно кодируется. Как правило, применяется кодировка base64, для работы с которой служит метод pack с аргументом m:

bin = File.read("new.gif")
str = [bin].pack("m")     # str закодирована.
orig = str.unpack("m")[0] # orig == bin

Старые почтовые клиенты работали с кодировкой uuencode/uudecode. В этом случае вложение просто добавляется в конец текста сообщения и ограничивается строками begin и end, причем в строке begin указываются также разрешения на доступ к файлу (которые можно и проигнорировать) и имя файла. Аргумент u метода pack позволяет представить строку в кодировке uuencode. Пример:

# Предположим, что mailtext содержит текст сообщения.
filename = "new.gif"
bin = File.read(filename)
encoded = [bin].pack("u")
mailtext << "begin 644 #{filename}"
mailtext << encoded
mailtext << "end"
# ...

На принимающей стороне мы должны извлечь закодированную информацию и декодировать ее методом unpack:

# ...
# Предположим, что 'attached' содержит закодированные данные
# (включая строки begin и end).
lines = attached.split("n")
filename = /begin ddd (.*)/.scan(lines[0]).first.first
encoded = lines[1..-2].join("n")
decoded = encoded.unpack("u") # Все готово к записи в файл.

Современные почтовые клиенты работают с почтой в формате MIME; даже текстовая часть сообщения обернута в конверт (хотя клиент удаляет все заголовки, прежде чем показать сообщение пользователю).

Подробное рассмотрение формата MIME заняло бы слишком много места, да и не относится к рассматриваемой теме. Но в следующем простом примере показано, как можно закодировать и отправить сообщение, содержащее текстовую часть и двоичное вложение. Двоичные куски обычно представлены в кодировке base64:

require 'net/smtp'
def text_plus_attachment(subject, body, filename)
 marker = "MIME_boundary"
 middle = "--#{marker}n"
 ending = "--#{middle}--n"
 content = "Content-Type: Multipart/Related; " +
  "boundary=#{marker}; " +
  "typw=text/plain"
 head1 = <<-EOF
MIME-Version: 1.0
#{content}
Subject: #{subject}
 EOF
 binary = File.read(filename)
 encoded = [binary].pack("m") # base64
 head2 = <<EOF
Content-Description: "#{filename}"
Content-Type: image/gif; name="#{filename}"
Content-Transfer-Encoding: Base64
Content-Disposition: attachment; filename="#{filename}"
 EOF
 # Возвращаем...
 head1 + middle + body + middle + head2 + encoded + ending
end
domain = "someserver.com"
smtp = "smtp.#{domain}"
user, pass = "elgar","enigma"
body = <<EOF
Это мое сообщение. Особо
говорить не о чем. Я вложил
небольшой GIF-файл.
          -- Боб
EOF
mailtext = text_plus_attachment("Привет...",body,"new.gif")
Net::SMTP.start(smtp, 25, domain, user, pass, :plain) do |mailer|
 mailer.sendmail(mailtext, '[email protected]',
  ['[email protected]'])
end

Оглавление книги


Генерация: 1.217. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз