part.rb 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. # encoding: utf-8
  2. module Mail
  3. class Part < Message
  4. # Creates a new empty Content-ID field and inserts it in the correct order
  5. # into the Header. The ContentIdField object will automatically generate
  6. # a unique content ID if you try and encode it or output it to_s without
  7. # specifying a content id.
  8. #
  9. # It will preserve the content ID you specify if you do.
  10. def add_content_id(content_id_val = '')
  11. header['content-id'] = content_id_val
  12. end
  13. # Returns true if the part has a content ID field, the field may or may
  14. # not have a value, but the field exists or not.
  15. def has_content_id?
  16. header.has_content_id?
  17. end
  18. def inline_content_id
  19. # TODO: Deprecated in 2.2.2 - Remove in 2.3
  20. STDERR.puts("Part#inline_content_id is deprecated, please call Part#cid instead")
  21. cid
  22. end
  23. def cid
  24. add_content_id unless has_content_id?
  25. uri_escape(unbracket(content_id))
  26. end
  27. def url
  28. "cid:#{cid}"
  29. end
  30. def inline?
  31. header[:content_disposition].disposition_type == 'inline' if header[:content_disposition]
  32. end
  33. def add_required_fields
  34. add_content_id unless has_content_id?
  35. super
  36. end
  37. def delivery_status_report_part?
  38. (main_type =~ /message/i && sub_type =~ /delivery-status/i) && body =~ /Status:/
  39. end
  40. def delivery_status_data
  41. delivery_status_report_part? ? parse_delivery_status_report : {}
  42. end
  43. def bounced?
  44. if action.is_a?(Array)
  45. !!(action.first =~ /failed/i)
  46. else
  47. !!(action =~ /failed/i)
  48. end
  49. end
  50. # Either returns the action if the message has just a single report, or an
  51. # array of all the actions, one for each report
  52. def action
  53. get_return_values('action')
  54. end
  55. def final_recipient
  56. get_return_values('final-recipient')
  57. end
  58. def error_status
  59. get_return_values('status')
  60. end
  61. def diagnostic_code
  62. get_return_values('diagnostic-code')
  63. end
  64. def remote_mta
  65. get_return_values('remote-mta')
  66. end
  67. def retryable?
  68. !(error_status =~ /^5/)
  69. end
  70. private
  71. def get_return_values(key)
  72. if delivery_status_data[key].is_a?(Array)
  73. delivery_status_data[key].map { |a| a.value }
  74. else
  75. delivery_status_data[key].value
  76. end
  77. end
  78. # A part may not have a header.... so, just init a body if no header
  79. def parse_message
  80. header_part, body_part = raw_source.split(/#{CRLF}#{WSP}*#{CRLF}/m, 2)
  81. if header_part =~ HEADER_LINE
  82. self.header = header_part
  83. self.body = body_part
  84. else
  85. self.header = "Content-Type: text/plain\r\n"
  86. self.body = raw_source
  87. end
  88. end
  89. def parse_delivery_status_report
  90. @delivery_status_data ||= Header.new(body.to_s.gsub("\r\n\r\n", "\r\n"))
  91. end
  92. end
  93. end