Commit | Line | Data |
f5baca29 |
1 | package Promulger::Dispatch; |
2 | use strict; |
3 | use warnings; |
4 | |
8ad89cb2 |
5 | use Email::Address; |
b179831b |
6 | use Email::MIME; |
f5baca29 |
7 | # XXX allow the user to specify their own Email::Sender::Transport -- apeiron, |
8 | # 2010-03-13 |
9 | use Email::Sender::Simple qw(sendmail); |
9f8395b9 |
10 | # XXX not yet -- apeiron, 2010-06-25 |
11 | #use Mail::Verp; |
f5baca29 |
12 | |
21baaef0 |
13 | use Promulger::Config; |
14 | |
15 | # XXX no bounce parsing yet -- apeiron, 2010-03-13 |
f5baca29 |
16 | sub dispatch { |
8ad89cb2 |
17 | my ($message) = @_; |
21baaef0 |
18 | my $config = Promulger::Config->config; |
f5baca29 |
19 | |
b179831b |
20 | my $email = Email::MIME->new($message); |
f7a55eac |
21 | my $recipient = $email->header('To'); |
8ad89cb2 |
22 | my $local_user = user_for_address($recipient); |
f7a55eac |
23 | my $sender = $email->header('From'); |
24 | my $subject = $email->header('Subject'); |
f5baca29 |
25 | |
8ad89cb2 |
26 | my $list = Promulger::List->resolve($local_user); |
f5baca29 |
27 | unless($list) { |
28 | reject($recipient, $sender); |
8ad89cb2 |
29 | return; |
f5baca29 |
30 | } |
31 | |
8ad89cb2 |
32 | if($local_user =~ /-request$/) { |
33 | handle_request($list, $sender, $local_user, $subject, $config); |
34 | return; |
f5baca29 |
35 | } |
36 | |
37 | # they don't have a request for us, so they want to post a message |
38 | post_message($list, $email, $config); |
8ad89cb2 |
39 | return; |
f5baca29 |
40 | } |
41 | |
42 | sub handle_request { |
21baaef0 |
43 | my ($list, $sender, $recipient, $subject) = @_; |
f5baca29 |
44 | |
8ad89cb2 |
45 | my $sender_address = bare_address($sender); |
46 | if($subject =~ /^\s*subscribe/i) { |
f7a55eac |
47 | print "going to subscribe $sender to " . $list->listname . "\n"; |
8ad89cb2 |
48 | $list->subscribe($sender_address) |
49 | or already_subscribed($list, $recipient, $sender_address); |
50 | } elsif($subject =~ /^\s*unsubscribe/i) { |
51 | $list->unsubscribe($sender_address) |
52 | or not_subscribed($list, $recipient, $sender_address); |
f5baca29 |
53 | } |
54 | } |
55 | |
56 | sub post_message { |
8ad89cb2 |
57 | my ($list, $email, $config) = @_; |
f5baca29 |
58 | |
f7a55eac |
59 | my $sender = $email->header('From'); |
8ad89cb2 |
60 | my $sender_address = bare_address($sender); |
f7a55eac |
61 | my $recipient = $email->header('To'); |
f5baca29 |
62 | |
8ad89cb2 |
63 | unless($list->accept_posts_from($sender_address) && $list->active) { |
64 | reject($recipient, $sender); |
65 | return; |
66 | } |
f5baca29 |
67 | |
68 | # they're allowed to post (subscribed or not), the list is active. let's do |
69 | # this thing. |
70 | |
71 | # XXX no MIME or other fancy handling for now -- apeiron, 2010-03-13 |
b179831b |
72 | my $body = $email->body_str; |
8ad89cb2 |
73 | for my $subscriber (keys %{$list->subscribers}) { |
f7a55eac |
74 | # my $verped_from = Mail::Verp->encode($recipient, $subscriber); |
75 | |
f5baca29 |
76 | # XXX we let the MTA create the message-id for us for now -- apeiron, |
77 | # 2010-03-13 |
b179831b |
78 | my $new_message = Email::MIME->create( |
f5baca29 |
79 | header => [ |
e9b4d3bc |
80 | From => $sender_address, |
81 | To => $subscriber, |
f7a55eac |
82 | Subject => $email->header('Subject'), |
e9b4d3bc |
83 | 'Reply-to' => $recipient, |
f5baca29 |
84 | ], |
85 | body => $body, |
86 | ); |
87 | # XXX no queuing or job distribution for now beyond what the MTA provides |
88 | # -- apeiron, 2010-03-13 |
f7a55eac |
89 | send_message($new_message); |
f5baca29 |
90 | } |
91 | } |
92 | |
f7a55eac |
93 | sub send_message { |
94 | my ($message) = @_; |
95 | my $config = Promulger::Config->config; |
96 | my ($class, $transport); |
97 | if($class = $config->{transport}) { |
98 | if($class !~ /::/) { |
99 | $class = "Email::Sender::Transport::${class}"; |
100 | } |
101 | } else { |
102 | $class = 'Email::Sender::Transport::Sendmail'; |
103 | } |
104 | Class::MOP::load_class($class); |
105 | $transport = $class->new; |
106 | sendmail( |
107 | $message, |
108 | { |
109 | transport => $transport, |
110 | } |
111 | ); |
112 | } |
113 | |
21baaef0 |
114 | # XXX make this actually not suck -- apeiron, 2010-03-13 |
115 | sub reject { |
8ad89cb2 |
116 | my ($recipient, $sender) = @_; |
b179831b |
117 | my $email = Email::MIME->create( |
21baaef0 |
118 | header => [ |
119 | From => $recipient, |
120 | To => $sender, |
121 | Subject => 'Rejected', |
122 | ], |
123 | body => <<BODY, |
124 | Sorry, your message to $recipient has been denied. |
125 | BODY |
126 | ); |
f7a55eac |
127 | send_message($email); |
21baaef0 |
128 | } |
129 | |
130 | sub not_subscribed { |
8ad89cb2 |
131 | my ($list, $recipient, $sender) = @_; |
b179831b |
132 | my $email = Email::MIME->create( |
8ad89cb2 |
133 | # XXX need admin address |
21baaef0 |
134 | header => [ |
8ad89cb2 |
135 | From => $recipient, |
21baaef0 |
136 | To => $sender, |
137 | Subject => 'Not subscribed', |
138 | ], |
139 | body => <<BODY, |
8ad89cb2 |
140 | Sorry, you are not subscribed to $list. |
21baaef0 |
141 | BODY |
142 | ); |
f7a55eac |
143 | send_message($email); |
21baaef0 |
144 | } |
145 | |
146 | sub already_subscribed { |
8ad89cb2 |
147 | my ($list, $recipient, $sender) = @_; |
b179831b |
148 | my $email = Email::MIME->create( |
21baaef0 |
149 | header => [ |
8ad89cb2 |
150 | From => $recipient, |
21baaef0 |
151 | To => $sender, |
152 | Subject => 'Already subscribed', |
153 | ], |
154 | body => <<BODY, |
8ad89cb2 |
155 | Sorry, you are already subscribed to $list. |
21baaef0 |
156 | BODY |
157 | ); |
f7a55eac |
158 | send_message($email); |
21baaef0 |
159 | } |
f5baca29 |
160 | |
8ad89cb2 |
161 | sub bare_address { |
162 | my ($full_addr) = @_; |
163 | my ($addr_obj) = Email::Address->parse($full_addr); |
164 | return $addr_obj->address; |
165 | } |
166 | |
167 | sub user_for_address { |
168 | my ($full_addr) = @_; |
169 | my ($addr_obj) = Email::Address->parse($full_addr); |
170 | return $addr_obj->user; |
171 | } |
172 | |
f5baca29 |
173 | 'http://www.shadowcat.co.uk/blog/matt-s-trout/oh-subdispatch-oh-subdispatch/'; |