I'm writing a plugin that needs fairly high-level control and idealy would use the results from other plugins. Are there hooks for qpsmtpd plugins to have plugins?
How can I package my module so that other can use it? How do I go about distributing it? Here's what I'm doing: I run several ISPs and we allow users to forward this mail off-site. Some users foward their mail to places that have a tendency to blacklist servers they receive spam from (AOL, Comcast, others). When someone forwards their mail, they forward their spam too. For various reasons, I don't want to try to do inbound spam filtering of forwarded mail. I'm using qpsmtpd to create an outbound spam-filtering smarthost. Since I don't want to drop people's mail w/o some indication of a problem, I'm building a quarentene for outbound spam. # # | | # decision | from one of our | not from one of our # matrix for | domains, or SPF | domains, and SPF doesn't match # spammy msgs | matches sender | # | | # -------------------+--------------------+-------------------------------- # | Quarentene with a | # to a filtered | bounce message and | Quarentene silently and send a "we've # domain (AOL etc) | send a message to | got your message" letter to recipient # | the recipient | # -------------------+--------------------+-------------------------------- # | | # not to a filtered | Quarentene with a | Let it through # domain | bounce message | # | | # -------------------+--------------------+-------------------------------- The existing qpsmtpd plugins for things like spamassassin don't fit my need well because I only want to invoke them in certain situations and I never want to change the headers of the message that's going through. A quarentene bounce will look something like: Sep 5 17:19:07 recovery postfix/smtp[17027]: 5CC09375D: to=<[EMAIL PROTECTED]>, relay=out.internet-mail-service.net[216.240.47.51], delay=1, status=bounced (host out.internet-mail-service.net[216.240.47.51] said: 552 Your message is quarentened because we think it is probably spam, if it is not spam, click http://out.internet-mail-service.net/quarentene.cgi/message/c2b54ff304da8240821aad17ab59d530 to release your message from quarentene or to choose to have the spam you send silently deleted instead of bounced (#5.2.1) (in reply to end of DATA command)) A message to a potential recipient will be something like: From: [% GET config.send_from %] To: [% GET recipient %] Subject: We are holding mail for you Date: [% GET now %] We are holding mail for you. The mail we are holding is most likely spam. We don't know for sure. If you would like to get your mail, please click the following link: [% GET recipient_url %] The reason we are holding the mail for you is because the service that handles email for @[% GET domain %] addresses has a policy of blacklisting mail from servers that send too much spam. We filter the email that is going from our servers to your server so that we don't get in trouble with your service's policy. As long as we keep receiving mail for you that we think is spam, we will continue to send you a reminder of the mail no more often than every [% GET renotify %] days. If you would prefer that we discard your mail silently please click here: [% GET recipient_url %]?action=DISCARD_MY_MAIL To get your mail, you will have to establish an email account with a service that does not have a blacklisting policy and provide that address to us. We will then redirect all the mail receive for [% GET recipient %] that we think might be spam to that address. We are not an intentional source of spam, but we do allow our customers to forward their email to other services. When they do this, we end up sending the spam our customers receive on to other servers. I'm happy to make my quarentene plugin available for others but I'm not sure how it can be packaged. It needs to control when spam filtering is active and what to do if a message is spammy. It needs to be paired with a CGI and some templates. For the moment, I'm building the spam filtering directly into my plugin. This isn't that hard for me as I've got code I can reuse from other parts of my operation. -Dave
