1 package Promulger::Dispatch;
4 use Scalar::Util 'blessed';
9 use Email::Sender::Simple ();
10 # XXX not yet -- apeiron, 2010-06-25
13 use Promulger::Config;
21 $proto->can('does') and
22 $proto->does('Email::Sender::Transport')
23 or die "transport must do Email::Sender::Transport role";
26 my $config = Promulger::Config->config;
28 if($class = $config->{mailer}) {
30 $class = "Email::Sender::Transport::${class}";
33 $class = 'Email::Sender::Transport::Sendmail';
35 Class::MOP::load_class($class);
41 my ($self, $message) = @_;
42 my $config = Promulger::Config->config;
44 my $email = Email::MIME->new($message);
45 my $recipient = $email->header('To');
46 my $local_user = $self->user_for_address($recipient);
47 my $sender = $email->header('From');
48 my $subject = $email->header('Subject');
50 my $list = Promulger::List->resolve($local_user);
52 $self->reject($recipient, $sender);
56 if($local_user =~ /-request$/) {
57 $self->handle_request($list, $sender, $local_user, $subject, $config);
61 # they don't have a request for us, so they want to post a message
62 $self->post_message($list, $email, $config);
67 my ($self, $list, $sender, $recipient, $subject) = @_;
68 my $sender_address = $self->bare_address($sender);
69 if($subject =~ /^\s*subscribe/i) {
70 $list->subscribe($sender_address)
71 or $self->already_subscribed($list, $recipient, $sender_address);
72 } elsif($subject =~ /^\s*unsubscribe/i) {
73 $list->unsubscribe($sender_address)
74 or $self->not_subscribed($list, $recipient, $sender_address);
78 # XXX this needs to be better -- apeiron, 2012-07-18
80 my ($self, $raw_message) = @_;
81 my $message = Email::MIME->new($raw_message);
82 require Mail::DeliveryStatus::BounceParser;
84 my $recipient = $message->header('To');
85 my $recipient_address = Email::Address->parse($recipient);
87 my $bounce = Mail::DeliveryStatus::BounceParser->new($message);
89 my $domain = $recipient_address->host;
90 my $redirect = Email::MIME->create(
92 From => $message->header('From'),
93 To => "postmaster@${domain}",
94 Subject => $message->header('Subject'),
96 body_str => $message->body_str,
98 $self->send_message($redirect);
100 my @addresses = $bounce->addresses;
101 my $list = Promulger::List->resolve($recipient_address->address);
102 for my $addr (@addresses) {
103 my $a = Email::Address->parse($addr);
104 my $raw_address = $a->address;
105 $list->unsubscribe($raw_address);
110 my ($self, $list, $email, $config) = @_;
111 my $sender = $email->header('From');
112 my $sender_address = $self->bare_address($sender);
113 my $recipient = $email->header('To');
115 unless($list->accept_posts_from($sender_address) && $list->active) {
116 $self->reject($recipient, $sender);
120 # XXX no MIME or other fancy handling for now -- apeiron, 2010-03-13
121 my $body = $email->body_str;
122 for my $subscriber (keys %{$list->subscribers}) {
123 # my $verped_from = Mail::Verp->encode($recipient, $subscriber);
125 # XXX we let the MTA create the message-id for us for now -- apeiron,
127 my $new_message = Email::MIME->create(
129 From => $sender_address,
131 Subject => $email->header('Subject'),
132 'Reply-to' => $recipient,
136 # XXX no queuing or job distribution for now beyond what the MTA provides
137 # -- apeiron, 2010-03-13
138 $self->send_message($new_message);
143 my ($self, $message) = @_;
144 Email::Sender::Simple::sendmail(
147 transport => $self->transport,
152 # XXX make this actually not suck -- apeiron, 2010-03-13
154 my ($self, $recipient, $sender) = @_;
155 my $email = Email::MIME->create(
159 Subject => 'Rejected',
162 Sorry, your message to $recipient has been denied.
165 $self->send_message($email);
169 my ($self, $list, $recipient, $sender) = @_;
170 my $email = Email::MIME->create(
171 # XXX need admin address
175 Subject => 'Not subscribed',
178 Sorry, you are not subscribed to $list.
181 $self->send_message($email);
184 sub already_subscribed {
185 my ($self, $list, $recipient, $sender) = @_;
186 my $email = Email::MIME->create(
190 Subject => 'Already subscribed',
193 Sorry, you are already subscribed to $list.
196 $self->send_message($email);
200 my ($self, $full_addr) = @_;
201 my ($addr_obj) = Email::Address->parse($full_addr);
202 return $addr_obj->address;
205 sub user_for_address {
206 my ($self, $full_addr) = @_;
207 my ($addr_obj) = Email::Address->parse($full_addr);
208 return $addr_obj->user;
211 'http://www.shadowcat.co.uk/blog/matt-s-trout/oh-subdispatch-oh-subdispatch/';