Ruby 转发带有附件的电子邮件

Ruby 转发带有附件的电子邮件,ruby,mail-gem,Ruby,Mail Gem,我希望在不下载附件然后重新/附加到新电子邮件的情况下执行此操作。 这就是我尝试过的: $emailslist.each do |e| Mail.deliver do from fromstr to "mailman@somedomain.com" subject "[Events] #{subjectstr}" if e.attachments.length>0 e.attachments.each do |a| add

我希望在不下载附件然后重新/附加到新电子邮件的情况下执行此操作。
这就是我尝试过的:

$emailslist.each do |e|
  Mail.deliver do
    from   fromstr
    to "mailman@somedomain.com"
    subject "[Events] #{subjectstr}"

    if e.attachments.length>0
      e.attachments.each do |a| 
       add_file a
     end
   end
 end
end

#error in 'e.attachments.each'=>undefined method `attachments' for
#<TypeError: can't convert nil into String> 

这是未经测试的,并不是真正试图找到或修复错误。这是为了展示你的代码应该是什么样子,用更地道的Ruby代码编写。因此,它可能会解决您看到的问题。如果没有,至少您会更好地了解应该如何编写代码:

require 'mail'
  • 为重用的文本字符串定义一些常量。在顶部执行此操作,这样您就不必在多个位置搜索代码来更改内容,从而可能会错过其中一个

    PATH_TO_FILES = "C:/Users/j.de_miguel/Desktop/mailman.forma"
    BODY_BOILERPLATE_FORMAT = "%s\nmailman@forma.culturadigital.cc para darte de baja escribe \"baja\" a info@culturadigital.cc"
    
  • 将方法分组到文件顶部的常量之后

  • 我们使用
    'a'
    打开,而不是
    'a+'
    。我们不需要读/写,我们只需要写
  • 这将根据需要打开和关闭文件
  • 自动关闭文件会进行刷新
  • 如果您经常调用log方法,那么有更好的方法可以做到这一点,但这不是一个重量级脚本
  • 我正在使用
    File.join
    根据路径构建文件名
    File.join
    知道路径分隔符并自动执行正确的操作
  • String.%%
    可以轻松创建标准输出格式

    def log(text)
    
      File.open(File.join(PATH_TO_FILES, "error_log2.txt"), 'a') do |log_file|
        log_file.puts "%s : %s" % [Time.now, text]
      end
    
    end
    
  • Ruby中的方法名是snake_大小写,而不是CamelCase

  • 没有理由拥有多个
    gsub也不需要条件测试。如果要清除的子字符串存在于字符串
    gsub
    中,则将执行此操作,否则将继续。链接
    gsub
    方法将代码减少到一行
  • gsub
    可能/应该是
    sub
    ,除非您知道字符串中可能有多个点击需要替换
  • return
    是冗余的,所以我们不使用它,除非我们显式地返回一个值以过早地离开一个块

    def delete_subject_recursion(subjstr)
    
      subjstr.gsub(/.\[FORMA 2013\]/,"").gsub(/((?i)Re: ){2,}/, "Re: ")
    
    end
    
  • 由于
    registed
    应为布尔值,因此使用来执行测试。如果找到任何匹配项,则退出并返回
    true

    def user_is_registered(mailaddr)
    
      registered = subscribers.any?{ |s| mailaddr == s }
      log("user #{ mailaddr } attempted to mailman") unless registered
    
      registered
    
    end
    
  • 使用
    foreach
    迭代文件的行

    subscribers = []
    File.foreach(File.join(PATH_TO_FILES, "subscribers2.txt")) do |line| 
      subscribers << line.chomp if line['@']
    end
    
    puts subscribers
    
    log('')
    
    Mail.defaults do
    
      retriever_method(
        :imap,
        {
          :address    => "imap.1and1.es",
          :port       => 143, 
          :user_name  => "mailman@somedomain.com",
          :password   => "xxxxxxxx",
          :enable_ssl => false 
        }
      )
    
      delivery_method(
        :smtp,
        {
          :address              => "smtp.1and1.es",
          :port                 => 587,
          :domain               => '1and1.es',
          :user_name            => 'mailman@somaedomain.com',
          :password             => 'xxxxxxxxxxxx',
          :authentication       => 'plain',
          :enable_starttls_auto => true  
        }
      )
    
    end
    
    #emailslist=Mail.find(keys: ['NOT','SEEN'])
    emailslist = [Mail.last]
    
    emailslist.each do |e|
    

可以使用后续条件
if
测试将其重构为简单的单行:

e.attachments.each { |a| add_file a.encoded } if e.attachments.length > 0
当你做一些简单的事情时,用这样一行就可以了。不要将它们用于更复杂的代码,因为这样会产生视觉噪音,这会使代码难以理解和阅读

但是让我们看看上面的代码实际上在做什么
e.attachments
在此上下文中似乎返回一个数组或某种可枚举集合,否则
每个
都不起作用
length
将告诉我们附件返回的“数组”(或任何数组)中存在多少元素

如果
length
为零,那么我们不想做任何事情,因此我们可以说:

e.attachments.each { |a| add_file a.encoded } unless e.attachments.empty?
(假设
附件
实现了
空?
方法。)

不过这也有点多余。如果
e.attachments
已为空,则每个
将做什么?它将检查
附件
是否返回了一个包含任何元素的数组,如果数组为空,它将完全跳过其块,就像触发了
条件时的后续
一样有效。所以,我们可以用这个来代替:

e.attachments.each { |a| add_file a.encoded }

Ruby样式指南:


第二个是基于第一个。

铁皮人的答案大多有效。我更改了添加附件的方式,因为他的版本不适合我

e.attachments.each { |a| attachments[a.filename] = a.decoded } if e.attachments.length > 0

它不起作用的原因是
e
没有值,它是
nil
。那么为什么
e
没有值呢?您的
$emailslist
是否为空?或者,它是否包含
nil
值?您没有向我们展示足够的信息来合理地回答您的问题。
e
不是零,否则它将无法通过if语句。如果我打印
e.attachments.inspect
它实际上会显示附件。如果使用
ruby-cwW2 path/to/your/application运行代码会发生什么情况?你正在滥用
$global
变量。哇,谢谢你的ruby课程!真的,非常感谢-我从来没有机会知道这种东西,否则,因为我总是独自编码+没有计算机科学背景:)/我会测试你的代码,看看它是如何运行的。没问题。每种语言都有其风格指南。我为Ruby添加了两个链接,一个基于另一个。把它们通读几遍总是好的,然后在学习的过程中定期重读。指南只是“指南”,而不是法律。使用基于可读性和可维护性的最有意义的内容,因为这有助于我们理解一年后编写的内容。我还为“添加附件”代码添加了一些重构。仍然不能保证代码能正常工作,因为我没有设置系统来测试它,但它还是更为惯用的Ruby。
e.attachments.each { |a| add_file a.encoded } unless e.attachments.empty?
e.attachments.each { |a| add_file a.encoded }
e.attachments.each { |a| attachments[a.filename] = a.decoded } if e.attachments.length > 0