Linode Forum
Linode Community Forums
 FAQFAQ    SearchSearch    MembersMembers      Register Register 
 LoginLogin [ Anonymous ] 
Post new topic  Reply to topic
Author Message
PostPosted: Sun Jul 31, 2011 12:40 pm 
Offline
Senior Member

Joined: Thu Oct 02, 2008 8:56 am
Posts: 99
I am currently developing a custom CMS and will hopefully be providing hosting services for small business / personal sites - and I would like to offer mail services.

Postfix / Dovecot side of things I think I can handle, but it would be nice to offer a web interface to procmail to handle server side basic filtering of incoming mail (users will NOT be given shell access). Procmail is what I personally use, and works best because it doesn't matter what client I connect with, the messages go where they are suppose to go.

I can code my own basic interface, but if one already exists, that would be better since it (hopefully) will already have been through testing / bug squashing. Anyone know of one?

The way I probably do it is to store the filtering information in XML that the web app modifies, and then use background process perl or php-cli to validate the XML and write a fresh .procmailrc upon modification of the XML by the web app, so the app doesn't need to execute command or have write permission to the .procmailrc - but if something like this already exists, I'd love to know.


Top
   
 Post subject:
PostPosted: Sun Jul 31, 2011 7:38 pm 
Offline
Senior Member
User avatar

Joined: Sat Aug 30, 2008 1:55 pm
Posts: 1739
Location: Rochester, New York
Hmm. Not entirely sure I'd throw XML into the situation; if I were doing it all over again, I'd probably just lob stuff into a database with a schema something like:

Code:
class Recipe:
  user = models.ForeignKey(User)  # the recipe belongs to this user
  order = models.IntegerField()  # sort order for this recipe
  flags = models.CharField()  # flags; could probably go to town with a M2M field or something, too
  action = models.TextField()  # exactly one action line

  @property
  def block(self):
    "Returns a configuration stanza appropriate for .procmailrc"
    recipe = (":0 %s\n" % self.flags) if self.flags else ":0\n"
    for condition in self.condition_set.all():
      recipe += "* %s\n" % condition
    recipe += self.action + "\n"
    return recipe

class Condition:
  condition = models.TextField()  # the regexp to match
  recipe = models.ForeignKey(Recipe)  # the condition belongs to this recipe

# instantiated like:
my_recipe = Recipe.objects.create(
  user = User.objects.get(username='jboehner')
  order = 10  # like MX records ;-)
  flags = 'c'  # generate a carbon copy
  action = '! president@whitehouse.gov'  # forward to POTUS
)
my_recipe.condition_set.create(
  condition = "^From: vicepresident@whitehouse.gov"  # match that sneaky under-the-table-dealin' joe
)


Then simply, as a user that can write to all of these locations:

Code:
from models import User, Recipe

for user in User.objects.filter(recipes_set__count__gt=0):
  with open('%s/.procmailrc' % user.homedir, 'w') as fp:
    for recipe in Recipe.objects.filter(user=user).order_by('order'):
      fp.write(recipe.block)


And bam, out they come. Apologies for the Django-specificness here; it was the easiest way to bang this out in a hurry. Testing, error handling, user interfacing, not writing out all the .procmailrc files every time this runs, the inevitable race conditions, and all that other stuff are left as an exercise for the reader.

I think Webmin has a module that does this -- it might be worth looking through its source for inspiration, too.

_________________
Code:
/* TODO: need to add signature to posts */


Top
   
 Post subject:
PostPosted: Mon Aug 01, 2011 7:01 am 
Offline
Senior Member

Joined: Thu Oct 02, 2008 8:56 am
Posts: 99
Your response is much appreciated, but I fundamentally disagree with using a DB for this. A proper RDBMS is overkill and NoSQL is really best suited for cases with lots of reads and writes and typically resides in memory.

I doubt lots of reads and writes are an issue here, most people who even make use of server side filtering will alter their filtering less than once a week, XML is excellent for file based data storage that doesn't change often, and most scripting languages have tools specifically designed to extract the needed info from it.


Top
   
 Post subject:
PostPosted: Mon Aug 01, 2011 8:20 am 
Offline
Senior Member
User avatar

Joined: Sat Aug 30, 2008 1:55 pm
Posts: 1739
Location: Rochester, New York
Map the schema to XML and you're set. I could go either way; it's just that in the environments I use, it adds another layer of handling and bloat that doesn't seem necessary for local data storage.

I get the feeling PHP generally doesn't make database access easy, which probably changes the equation significantly. In any case, use the tools you got.

_________________
Code:
/* TODO: need to add signature to posts */


Top
   
 Post subject:
PostPosted: Tue Aug 02, 2011 3:59 am 
Offline
Senior Member

Joined: Thu Oct 02, 2008 8:56 am
Posts: 99
database access is easy in php.

I just don't like to use them where flat file seems better (cases when relational queries and speed aren't necessary) - especially if/when I need to move accounts around from one server to another.


Top
   
Display posts from previous:  Sort by  
Post new topic  Reply to topic


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
RSS

Powered by phpBB® Forum Software © phpBB Group