Class: Redwood::ReplyMode

Inherits:
EditMessageMode show all
Defined in:
lib/sup/modes/reply_mode.rb

Constant Summary collapse

REPLY_TYPES =
[:sender, :recipient, :list, :all, :user]
TYPE_DESCRIPTIONS =
{
  :sender => "Sender",
  :recipient => "Recipient",
  :all => "All",
  :list => "Mailing list",
  :user => "Customized"
}

Constants inherited from EditMessageMode

EditMessageMode::DECORATION_LINES, EditMessageMode::FORCE_HEADERS, EditMessageMode::MULTI_HEADERS, EditMessageMode::NON_EDITABLE_HEADERS

Instance Attribute Summary

Attributes inherited from EditMessageMode

#body, #header, #status

Attributes inherited from LineCursorMode

#curpos

Attributes inherited from ScrollMode

#botline, #leftcol, #status, #topline

Attributes inherited from Mode

#buffer

Instance Method Summary collapse

Methods inherited from EditMessageMode

#[], #alternate_edit_message, #attach_file, #default_edit_message, #delete_attachment, #edit_cc, #edit_message, #edit_message_async, #edit_message_async_resume, #edit_message_or_field, #edit_subject, #edit_to, #killable?, #lines, #save_message_to_file, #set_sig_edit_flag, #unsaved?

Methods inherited from LineCursorMode

#cleanup, #draw

Methods inherited from ScrollMode

#at_bottom?, #at_top?, #cancel_search!, #col_jump, #col_left, #col_right, #continue_search_in_buffer, #draw, #ensure_mode_validity, #half_page_down, #half_page_up, #in_search?, #jump_to_col, #jump_to_end, #jump_to_left, #jump_to_line, #jump_to_start, #line_down, #line_up, #page_down, #page_up, #resize, #rightcol, #search_goto_line, #search_goto_pos, #search_in_buffer, #search_start_line

Methods inherited from Mode

#blur, #cancel_search!, #cleanup, #draw, #focus, #handle_input, #help_text, #in_search?, keymap, keymaps, #killable?, load_all_modes, make_name, #name, #pipe_to_process, register_keymap, #resize, #resolve_input, #save_to_file, #status, #unsaved?

Constructor Details

#initialize(message, type_arg = nil) ⇒ ReplyMode

Returns a new instance of ReplyMode.



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/sup/modes/reply_mode.rb', line 45

def initialize message, type_arg=nil
  @m = message
  @edited = false

  ## it's important to put this early because it forces a read of
  ## the full headers (most importantly the list-post header, if
  ## any)
  body = reply_body_lines message
  @body_orig = body

  ## first, determine the address at which we received this email. this will
  ## become our From: address in the reply.
  hook_reply_from = HookManager.run "reply-from", :message => @m

  ## sanity check that selection is a Person (or we'll fail below)
  ## don't check that it's an Account, though; assume they know what they're
  ## doing.
  if hook_reply_from && !(hook_reply_from.is_a? Person)
    info "reply-from returned non-Person, using default from."
    hook_reply_from = nil
  end

  ## determine the from address of a reply.
  ## if we have a value from a hook, use it.
  from = if hook_reply_from
    hook_reply_from
  ## otherwise, try and find an account somewhere in the list of to's
  ## and cc's and look up the corresponding name form the list of accounts.
  ## if this does not succeed use the recipient_email (=envelope-to) instead.
  ## this is for the case where mail is received from a mailing lists (so the
  ## To: is the list id itself). if the user subscribes via a particular
  ## alias, we want to use that alias in the reply.
  elsif(b = (@m.to.collect {|t| t.email} + @m.cc.collect {|c| c.email} + [@m.recipient_email] ).find { |p| AccountManager. p })
    a = AccountManager.(b)
    Person.new a.name, b
  ## if all else fails, use the default
  else
    AccountManager.
  end

  ## now, determine to: and cc: addressess. we ignore reply-to for list
  ## messages because it's typically set to the list address, which we
  ## explicitly treat with reply type :list
  to = @m.is_list_message? ? @m.from : (@m.replyto || @m.from)

  ## next, cc:
  cc = (@m.to + @m.cc - [from, to]).uniq

  ## one potential reply type is "reply to recipient". this only happens
  ## in certain cases:
  ## if there's no cc, then the sender is the person you want to reply
  ## to. if it's a list message, then the list address is. otherwise,
  ## the cc contains a recipient.
  useful_recipient = !(cc.empty? || @m.is_list_message?)

  @headers = {}
  @headers[:recipient] = {
    "To" => cc.map { |p| p.full_address },
    "Cc" => [],
  } if useful_recipient

  ## typically we don't want to have a reply-to-sender option if the sender
  ## is a user account. however, if the cc is empty, it's a message to
  ## ourselves, so for the lack of any other options, we'll add it.
  @headers[:sender] = {
    "To" => [to.full_address],
    "Cc" => [],
  } if !AccountManager.is_account?(to) || !useful_recipient

  @headers[:user] = {
    "To" => [],
    "Cc" => [],
  }

  not_me_ccs = cc.select { |p| !AccountManager.is_account?(p) }
  @headers[:all] = {
    "To" => [to.full_address],
    "Cc" => not_me_ccs.map { |p| p.full_address },
  } unless not_me_ccs.empty?

  @headers[:list] = {
    "To" => [@m.list_address.full_address],
    "Cc" => [],
  } if @m.is_list_message?

  refs = gen_references

  types = REPLY_TYPES.select { |t| @headers.member?(t) }
  @type_selector = HorizontalSelector.new "Reply to:", types, types.map { |x| TYPE_DESCRIPTIONS[x] }

  hook_reply = HookManager.run "reply-to", :modes => types, :message => @m

  @type_selector.set_to(
    if types.include? type_arg
      type_arg
    elsif types.include? hook_reply
      hook_reply
    elsif @m.is_list_message?
      :list
    elsif @headers.member? :sender
      :sender
    else
      :recipient
    end)

  headers_full = {
    "From" => from.full_address,
    "Bcc" => [],
    "In-reply-to" => "<#{@m.id}>",
    "Subject" => Message.reify_subj(@m.subj),
    "References" => refs,
  }.merge @headers[@type_selector.val]

  HookManager.run "before-edit", :header => headers_full, :body => body

  super :header => headers_full, :body => body, :twiddles => false
  add_selector @type_selector
end