Class: Hermeneutics::Mail

Inherits:
Message show all
Defined in:
lib/hermeneutics/mail.rb

Constant Summary collapse

SENDMAIL =
"/usr/sbin/sendmail"
SPOOLDIR =
"/var/mail"
SPOOLFILE =
nil
MAILDIR =
"~/Mail"
SYSDIR =
".hermeneutics"
LOGLEVEL =
:ERR
LOGFILE =
"#{File.basename $0}.log"
LEVEL =
%i(
  NON
  ERR
  INF
  DBG
).inject Hash.new do |h,k| h[k] = h.length ; h end

Constants inherited from Message

Hermeneutics::Message::MIME

Instance Attribute Summary

Attributes inherited from Message

#body, #headers

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Message

#[], #body_binary=, #body_decoded, #body_text=, #has?, #header, #inspect, #is_multipart?, #to_s, #transfer_encoding

Methods inherited from Mime

find, inherited

Constructor Details

#initialize(headers, body, from, created) ⇒ Mail

Returns a new instance of Mail.



30
31
32
33
# File 'lib/hermeneutics/mail.rb', line 30

def initialize headers, body, from, created
  super headers, body
  @plain_from, @created = from, created
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Hermeneutics::Message

Class Method Details

.box(path = nil, default_format = nil) ⇒ Object



98
99
100
101
# File 'lib/hermeneutics/mail.rb', line 98

def box path = nil, default_format = nil
  @cache ||= {}
  @cache[ path] ||= find_box path, default_format
end

.createObject



24
25
26
# File 'lib/hermeneutics/mail.rb', line 24

def create
  new nil, nil, nil, nil
end

.expand_maildirObject



139
140
141
# File 'lib/hermeneutics/mail.rb', line 139

def expand_maildir
  File.expand_path self::MAILDIR, "~"
end

.expand_sysdirObject



143
144
145
# File 'lib/hermeneutics/mail.rb', line 143

def expand_sysdir
  File.expand_path self::SYSDIR, expand_maildir
end

.log(type, *message) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/hermeneutics/mail.rb', line 126

def log type, *message
  self::LOGFILE or return
  return if LEVEL[ type] > LEVEL[ self::LOGLEVEL].to_i
  l = File.expand_path self::LOGFILE, expand_sysdir
  File.open l, "a" do |log|
    log.puts "[#{Time.new}] [#$$] [#{type}] #{message.join ' '}"
  end
  nil
rescue Errno::ENOENT
  d = File.dirname l
  Dir.mkdir! d and retry
end

.parse(input, from = nil, created = nil) ⇒ Object



17
18
19
20
21
22
# File 'lib/hermeneutics/mail.rb', line 17

def parse input, from = nil, created = nil
  input.gsub! "\r\n", "\n"
  parse_hb input do |h,b|
    new h, b, from, created
  end
end

Instance Method Details

#createdObject



39
40
41
# File 'lib/hermeneutics/mail.rb', line 39

def created
  @created ||= Time.now
end

#pipe(cmd, *args) ⇒ Object

:call-seq:

obj.pipe( cmd, *args)           -> status

Pipe into an external program. If a block is given, the programs output will be yielded there.



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/hermeneutics/mail.rb', line 173

def pipe cmd, *args
  log :INF, "Piping through:", cmd, *args
  ri, wi = IO.pipe
  ro, wo = IO.pipe
  child = fork do
    wi.close ; ro.close
    $stdout.reopen wo ; wo.close
    $stdin .reopen ri ; ri.close
    exec cmd, *args
  end
  ri.close ; wo.close
  t = Thread.new wi do |wi|
    begin
      wi.write to_s
    ensure
      wi.close
    end
  end
  begin
    r = ro.read
    yield r if block_given?
  ensure
    ro.close
  end
  t.join
  Process.wait child
  $?.success? or
    log :ERR, "Pipe failed with error code %d." % $?.exitstatus
  $?
end

#plain_fromObject



35
36
37
# File 'lib/hermeneutics/mail.rb', line 35

def plain_from
  @plain_from ||= find_plain_from
end

#receiversObject



47
48
49
# File 'lib/hermeneutics/mail.rb', line 47

def receivers
  addresses_of :to, :cc, :bcc
end

#save(mailbox = nil, default_format = nil) ⇒ Object

:call-seq:

obj.save( path, default_format = nil)           -> mb

Save into local mailbox.



161
162
163
164
165
# File 'lib/hermeneutics/mail.rb', line 161

def save mailbox = nil, default_format = nil
  b = self.class.box mailbox, default_format
  log :INF, "Delivering to", b.path
  b.store self
end

#send!(conn = nil, *tos) ⇒ Object

:call-seq:

obj.send!( smtp, *tos)                -> response

Send by SMTP.

Be aware that #send without bang is a standard Ruby method.



235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/hermeneutics/mail.rb', line 235

def send! conn = nil, *tos
  if tos.empty? then
    tos = (addresses_of :to, :cc).map { |t| t.plain }
  else
    tos.flatten!
  end
  f, m = true, ""
  to_s.each_line { |l|
    if f then
      f = false
      next if l =~ /^From /
    end
    m << l
  }
  open_smtp conn do |smtp|
    log :INF, "Sending to", *tos
    smtp.mail_from headers.from.first.plain
    tos.each { |t| smtp.rcpt_to t }
    smtp.data m
  end
rescue NoMethodError
  raise "Missing field: #{$!.name}."
end

#sendersObject



43
44
45
# File 'lib/hermeneutics/mail.rb', line 43

def senders
  addresses_of :from, :sender, :return_path
end

#sendmail(*tos) ⇒ Object

:call-seq:

obj.sendmail( *tos)                -> status

Send by sendmail; leave the tos list empty to use Sendmail’s -t option.



210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/hermeneutics/mail.rb', line 210

def sendmail *tos
  args = []
  if tos.empty? then
    args.push "-t"
  else
    tos.flatten!
    tos.each { |t|
      to = case t
        when Addr then t.plain
        else           t.delete %q-,;"'<>(){}[]$&*?-   # security
      end
      args.push to
    }
  end
  pipe self::SENDMAIL, *args
end