Возникает вопрос: «А как вообще почта поступает в программу mail2news
?» Ведь она, похоже, читает из стандартного ввода. Автор рекомендует следующую настройку: сначала в файле .forward
программы sendmail
вся входящая почта перенаправляется на программу procmail
. Файл .procmail
конфигурируется так, чтобы извлекать сообщения, приходящие из списка рассылки, и по конвейеру направлять их программе mail2news
. Уточнить детали можно в документации, сопровождающей приложение RubyMirror (в архиве RAA). Если вы работаете не в UNIX, то придется изобрести собственную схему конфигурирования.
Ну а все остальное расскажет сам код, приведенный в листингах 18.6 и 18.7.
Листинг 18.6. Перенаправление почты в конференцию
# mail2news: Принимает почтовое сообщение и отправляет
# его в конференцию.
require "nntp"
include NNTP
require "params"
# Прочитать сообщение, выделив из него заголовок и тело.
# Пропускаются только определенные заголовки.
HEADERS = %w{From Subject References Message-ID
Content-Type Content-Transfer-Encoding Date}
allowed_headers = Regexp.new(%{^(#{HEADERS.join("|")}):})
# Прочитать заголовок. Допускаются только некоторые заголовки.
# Добавить строки Newsgroups и X-rubymirror.
head = "Newsgroups: #{Params::NEWSGROUP}\n"
subject = "unknown"
while line = gets
exit if line /^#{Params::LOOP_FLAG}/о # Такого не должно быть!
break if line =~ /^s*$/
next if line =~ /^\s/
next unless line =~ allowed_headers
# Вырезать префикс [ruby-talk:nnnn] из темы, прежде чем
# отправлять в конференцию.
if line =~ /^Subject:\s*(.*)/
subject = $1
# Следующий код вырезает специальный номер ruby-talk
# из начала сообщения в списке рассылки, перед тем
# как отправлять его новостному серверу.
line.sub!(/\[ruby-talk:(\d+)\]\s*/, '')
subject = "[#$1] #{line}"
head << "X-ruby-talk: #$1\n"
end
head << line
end
head << "#{Params::LOOP_FLAG}\n"
body = ""
while line = gets
body << line
end
msg = head + "\n" + body
msg.gsub!(/\r?\n/, "\r\n")
nntp = NNTPIO.new(Params::NEWS_SERVER)
raise "Failed to connect" unless nntp.connect
nntp.post(msg)
Листинг 18.7. Перенаправление конференции в почту
##
# Простой сценарий для зеркалирования трафика
# из конференции comp.lang.ruby в список рассылки ruby-talk.
#
# Вызывается периодически (скажем, каждые 20 минут).
# Запрашивает у новостного сервера все сообщения с номером,
# большим номера последнего сообщения, полученного
# в прошлый раз. Если таковые есть, то читает сообщения,
# отправляет их в список рассылки и запоминает номер последнего.
require 'nntp'
require 'net/smtp'
require 'params'
include NNTP
##
# # Отправить сообщения в список рассылки. Сообщение должно
# быть отправлено участником списка, хотя в строке From:
# может стоять любой допустимый адрес.
#
def send_mail(head, body)
smtp = Net::SMTP.new
smtp.start(Params::SMTP_SERVER)
smtp.ready(Params::MAIL_SENDER, Params::MAILING_LIST) do |a|
a.write head
a.write "#{Params::LOOP_FLAG}\r\n"
a.write "\r\n"
a.write body
end
end
##
# Запоминаем идентификатор последнего прочитанного из конференции
# сообщения.
begin
last_news = File.open(Params::LAST_NEWS_FILE) {|f| f.read}.to_i
rescue
last_news = nil
end
##
# Соединяемся с новостным сервером и получаем номера сообщений
# из конференции comp.lang.ruby.
#
nntp = NNTPIО.new(Params::NEWS_SERVER)
raise "Failed to connect" unless nntp.connect
count, first, last = nntp.set_group(Params::NEWSGROUP)
##
# Если номер последнего сообщения не был запомнен раньше,
# сделаем это сейчас.
if not last_news
last_news = last
end
##
# Перейти к последнему прочитанному ранее сообщению
# и попытаться получить следующие за ним. Это может привести
# к исключению, если сообщения с указанным номером
# не существует, но мы не обращаем на это внимания.
begin
nntp.set_stat(last_news)
rescue
end
##
# Читаем все имеющиеся сообщения и отправляем каждое
# в список рассылки.
new_last = last_news
begin
loop do
nntp.set_next
head = ""
body = ""
new_last, = nntp.get_head do |line|
head << line
end
Читать дальше
Конец ознакомительного отрывка
Купить книгу