SlideShare a Scribd company logo
Writing Applications
   with Qpsmtpd



      Fred Moyer

      fred@redhotpenguin.com
Qpsmtpd
●   Perl SMTP daemon written by Ask Bjørn Hansen
●   “mod_perl” of smtp
●   Plugin API makes writing extensions fun
●   Works with Qmail, Postfix, and Exim
●   Stock plugins include spam and virus protection
●   If you've tried to extend a C based smtp
    daemon you've felt pain at some point
Setting it up
●   Read the article by Matt Sergeant [1]
●   Install using RPMs if you can
    http://wiki.qpsmtpd.org/rpm-install_howto
●   Installing from source is easy also
    http://wiki.qpsmtpd.org/quick-install_howto
●   Telnetting to port 25 works for testing...
●   SWAKS is your friend [3]
●   qpsmtpd@perl.org is also your friend
My config file
  /home/smtpd/qpsmtpd/config/plugins
auth/auth_vpopmail_sql # set db auth in the plugin code
denysoft_greylist redhotpenguin.com taperfriendlymusic.org
quit_fortune
check_earlytalker
count_unrecognized_commands 4
check_relay
# require_resolvable_fromhost
# ^^ enable this to prevent zombies
check_delivery normal 1 127.0.0.1 vppmail dbuser dbpass
My config file
  /home/smtpd/qpsmtpd/config/plugins

# rhsbl <- these blacklist plugins blacklist
# dnsbl <- yahoo.com et al. sometimes!
check_badmailfrom
check_badrcptto
check_spamhelo
# sender_permitted_from
rcpt_ok # this is the last rcpt plugin
My config file
  /home/smtpd/qpsmtpd/config/plugins
virus/klez_filter
spamassassin reject_threshold 20 munge_subject_threshold 5
virus/clamav
# here is my first qpsmtpd application
craigslist recipient craig_qp@redhotpenguin.com site 
 http://www.craigslist.org login fred@redhotpenguin.com 
 password fredspass
queue/qmail-queue # leave enabled to forward the email
Many plugins available
●   http://wiki.qpsmtpd.org/plugins
●   Spam
●   Virus
●   Authentication – Vpopmail, PAM, text file, LDAP...
●   Plugins are generally geared towards keeping the
    spam out, and letting the good mail through
Your first plugin
●   Start with good examples

●   Read Matt Sergeant's O'reilly article [1]

●   Read the source for existing plugins

●   perldoc README.plugins ;)
A simple subject filter
 ●   Spam filters don't catch everything
block_subject [ all | [ domain1, domain2 ... ] ]

sub init {
 my ($self, $qp, @domains) = @_;
 unless (defined $domains[0]) {
   die “block_subject needs proper confign”;
 }

 $self->{_args}->{domains} = @domains;
 my $content = <<”SUBJECTS”;
YOUR REPRESENTATIVE ASSISTANCE IS NEEDED
Message From eBay Member
The Ultimate Online Pharmaceutical
SUBJECTS
A simple subject filter
    my @subjects = split(“n”, $block_content);
    $self->{_args}->{subjects} = @subjects;

    $self->log(LOGDEBUG,
     “Blocking subjects $block_content”);
}

sub hook_data_post {
 my ($self, $transaction) = @_;
 if ($self->{_args}->{domains}->[0] eq 'all') {
   if ($self->_blocked_subject($transaction)) {
     return DENY;
   }
 }
 else {
A simple subject filter
    # Check each domain
    my @recip_domains = map { $_->host }
     $transaction->recipients;
    foreach my $domain (@recip_domains) {

     # Deny the email if the subject is in our blacklist
     if (grep { $_ =~ m/^$domain$/ } @{$self->{_args}->{domains}
       && $self->blocked_subject($transaction))
       {
         return DENY;
       }
     }
    }
    return DECLINED;
}
A simple subject filter
sub blocked_subject {
 my ($self, $transaction) = @_;
 my $subject = $transaction->header->get('Subject');
 chomp($subject);

    if (grep { $_ =~ m/$subject$/i } @{$self->{_args}->{subjects}})
      {
        $self->log(LOGINFO, “block_subject invoked for $subject”);
        return 1;
      }
    return;
}
SMTP Applications?

●   SMTP to HTTP Gateways
●   Automate tedious processes
●   Use emails to interact with applications
●   Today's PDAs have IMAP based email
    but aren't very good at serving web pages
A Practical Application
●   The problem at hand
    ●   A couple hundred things we couldn't sell
    ●   Throwing away is bad for the environment
        (and costs money)
    ●   http://www.craigslist.org - someone wants it
●   But taking a picture of everything and posting
    an ad to Craigslist is a lot of clicking
●   I don't like to click, I like to write Perl
A Practical Application
●   Possible solutions
    ●   No internet connection
    ●   I could make a list of the items at hand
    ●   Call a friend and have him post
        ( no images though, and one less friend )
    ●   Or drive to local shop with wireless
        and click away
A Practical Application
●   My phone has a built in camera and
    email client
●   I could take pictures and email them to
    myself with a description, and post from
    home
●   That's repeating myself though, and too
    much work
A Practical Application
●   A Qpsmtpd plugin to solve this problem?
●   It came down to being Lazy
●   Being able to post an item at will is
    preferable to batching transactions
●   Bonus points for a per item picture,
    response rates for items with pictures
    are much higher than without
A Waste of Time?
●   At 3 minutes overhead per item the
    transaction overhead is 7.5 hours for
    150 items
●   At 30 seconds overhead per item the
    transaction overhead is 75 minutes for
    150 items
●   Total time spent thinking, coding,
    testing and deploying was about 3 hours
●   Bonus points for writing fun code!
The Source
  ●   Initialization
use WWW::Mechanize;
use Data::Dumper;

sub init {
  my ($self, $qp, %args) = @_;
  $self->{_args} = %args;
  $self->{_mech} = WWW::Mechanize->new;
  $self->log(LOGDEBUG, “Craigslist plugin init: n” .
   Dumper(%args));
}
The Source
 ● Start processing after all data is received
 ● Check authorization first



sub hook_data_post {
 my ($self, $transaction) = @_;

 return DECLINED unless
  (($transaction->recipients->[0]->address eq
    $self->{_args}->{recipient})
  && $self->qp->connection->relay_client);
The Source
   ●   Get the subject and body

my $subject = $transaction->header->get('Subject');
my $body;
while ( my $line = $transaction->body_getline ) {
  $body .= $line;
}
use Email::MIME;
my $em = Email::MIME->new($subject . $body);
The Source
 ●   Get the attached images and save them
use Email::MIME::Attachment::Stripper;
my $stripper =
  Email::MIME::Attachment::Stripper->new($em);
my $attachments = $stripper->attachments;
if (@attachments) {
  foreach my $at (@attachments) {
    my $fh;
    open($fh, “>”, “/tmp/” . $at->{filename}) || die $!;
    print $fh $at->{payload};
    close($fh);
  }
}
The Source
   ●   Login to http://www.craigslist.org
$self->{_mech}->get($self->{_args}->{site});
$self->{_mech}->submit_form(
  form_name => “login”,
  fields => {
    inputEmailHandle => $self->{_args}->{login},
    inputPassword     => $self->{_args}->{password}
  });
if (! $self->{_mech}->success ) {
  $transaction->body_write(“Error during login”);
  return DECLINED;
}
The Source
   ●   Login to www.craigslist.org
$self->{_mech}->get($self->{_args}->{site});
$self->{_mech}->submit_form(
  form_name => “login”,
  fields => {
    inputEmailHandle => $self->{_args}->{login},
    inputPassword     => $self->{_args}->{password}
  });
if (! $self->{_mech}->success ) {
  $transaction->body_write(“Error during login”);
  return DECLINED;
}
The Source
     ●   Walk the website

$self->{_mech}->follow_link(
  text_regex => qr/wanted/ );
if (! $self->{_mech}->success ) {
  $transaction->body_write(“Error following wanted link”);
  return DECLINED;
}

# ... click through a few more links to get to ad posting
The Source
  ●   Post the ad
$self->{_mech}->submit_form(
  form_number => 1,
  button => 'imagesForm',
  fields => {
    PostingTitle => $subject,
    PostingBody => $body,
    Ask          => 0,
  });
if (! $self->{_mech}->success) {
  $transaction->body_write(“Error, could not post ad”);
  return DECLINED;
}
The Source
 ●   Post the images
foreach my $at (@attachments) {
  $self->{_mech}->submit_form(
    form_number => 1,
    fields => { file1 => '/tmp/' . $at->{filename} }
  );
  if (! $self->{_mech}->success) {
    $transaction->write_body(
      “Error adding image “ . $at->{filename});
    return DECLINED;
  }
  unlink('/tmp/' . $at->{filename});
}
We're done
●   Grab the PDA
●   Take a picture
●   Compose an email
●   Receive a flood of responses
    ( still need to write that part of the app )
Perl did the work
●   No clicking (except taking the photo)
●   No dealing with a cumbersome web
    based application
●   Our energy goes to where it's needed most
●   All we had to do was code up a defined process
Recommended API Practices
●   Run your application last after all other
    plugins, before the queue plugin

●   Forward the email to the sender as a
    receipt

●   Use a separate To: address for each app,
    one that isn't vulnerable to dictionary attacks
Giving feedback to the User
●   Indicate success or failure
●   Let them know why it failed -
    $transaction->write_body(“Why it failed”);
●   Be strict in what you accept – the spammers
    will find your openings eventually
Recommended AAA Approaches
●   Require users to authenticate via SMTP auth
    - as secure as normal SMTP transactions
    $self->qp->connection->relay_client == 1
●   Combine username with To: address and
    match that against sender address, fairly
    secure but not unbreakable
    To: fred_craigslist@domain.com,
    From: fred@fredsdomain.com
●   Greylisting can help here but remember
    that zombies can retry with dictionary attacks
Recommended AAA Approaches
●   Require the user register their email address
    and verify they are a real person
●   Don't use a password in the email -
    most users have one password and will
    blissfully use it here as well
●   Use good judgement in weighing ease of
    use vs. security in authentication – err on
    the side of security.
Recommended AAA Approaches
 ●   Don't use this approach to build secure
     apps unless you _really_ know what you
     are doing. Better yet, just don't do it.
 ●   Don't send sensitive information in plain
     text email
 ●   This approach is about making automated
     tasks easy from insecure clients (PDAs).
     Proceed as such.
More Ideas
●   Reply to those annoying “DO NOT REPLY”
    emails from Bugzilla, et al.
●   Check the weather
●   Check the traffic report
●   Next bus
●   Post to a picture blog from your PDA
●   Any process that is repeatable and boring
Credits
●   The Qpsmtpd community

●   Ask Bjørn Hansen for authoring Qpsmtpd

●   Matt Sergeant and Robert Spier for
    listening to my crazy ideas on #qpsmtpd
References
[1] – Using Qpsmtpd, Matt Sergeant
http://www.oreillynet.com/pub/a/sysadmin/2005/09/15/qpsmtpd.html

[2] – The Qpsmtpd Wiki
http://wiki.qpsmtpd.org

[3] – SWAKS
http://jetmore.org/john/code/#swaks
Slides

These slides are freely available at

 http://www.redhotpenguin.com/talks


       Thank you NPW 2006!

More Related Content

What's hot

Create responsive websites with Django, REST and AngularJS
Create responsive websites with Django, REST and AngularJSCreate responsive websites with Django, REST and AngularJS
Create responsive websites with Django, REST and AngularJS
Hannes Hapke
 
AJAX Transport Layer
AJAX Transport LayerAJAX Transport Layer
AJAX Transport Layer
Siarhei Barysiuk
 
Crafting Quality PHP Applications (ConFoo YVR 2017)
Crafting Quality PHP Applications (ConFoo YVR 2017)Crafting Quality PHP Applications (ConFoo YVR 2017)
Crafting Quality PHP Applications (ConFoo YVR 2017)
James Titcumb
 
Cucumber Ru09 Web
Cucumber Ru09 WebCucumber Ru09 Web
Cucumber Ru09 Web
Joseph Wilk
 
[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress Development[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress Development
Adam Tomat
 
jQuery
jQueryjQuery
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
James Titcumb
 
Scalable web application architecture
Scalable web application architectureScalable web application architecture
Scalable web application architecture
postrational
 
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
James Titcumb
 
Webinar: AngularJS and the WordPress REST API
Webinar: AngularJS and the WordPress REST APIWebinar: AngularJS and the WordPress REST API
Webinar: AngularJS and the WordPress REST API
WP Engine UK
 
My app is secure... I think
My app is secure... I thinkMy app is secure... I think
My app is secure... I think
Wim Godden
 
WCLV13 JavaScript
WCLV13 JavaScriptWCLV13 JavaScript
WCLV13 JavaScript
Jeffrey Zinn
 
RSpec 2 Best practices
RSpec 2 Best practicesRSpec 2 Best practices
RSpec 2 Best practices
Andrea Reginato
 
Broadleaf Presents Thymeleaf
Broadleaf Presents ThymeleafBroadleaf Presents Thymeleaf
Broadleaf Presents Thymeleaf
Broadleaf Commerce
 
Keeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and Webpack
Ignacio Martín
 
Ruby gems
Ruby gemsRuby gems
Ruby gems
Papp Laszlo
 
Crafting Quality PHP Applications (PHP Benelux 2018)
Crafting Quality PHP Applications (PHP Benelux 2018)Crafting Quality PHP Applications (PHP Benelux 2018)
Crafting Quality PHP Applications (PHP Benelux 2018)
James Titcumb
 
Beijing Perl Workshop 2008 Hiveminder Secret Sauce
Beijing Perl Workshop 2008 Hiveminder Secret SauceBeijing Perl Workshop 2008 Hiveminder Secret Sauce
Beijing Perl Workshop 2008 Hiveminder Secret SauceJesse Vincent
 
Thymeleaf Introduction
Thymeleaf IntroductionThymeleaf Introduction
Thymeleaf Introduction
Anthony Chen
 

What's hot (20)

Create responsive websites with Django, REST and AngularJS
Create responsive websites with Django, REST and AngularJSCreate responsive websites with Django, REST and AngularJS
Create responsive websites with Django, REST and AngularJS
 
AJAX Transport Layer
AJAX Transport LayerAJAX Transport Layer
AJAX Transport Layer
 
Crafting Quality PHP Applications (ConFoo YVR 2017)
Crafting Quality PHP Applications (ConFoo YVR 2017)Crafting Quality PHP Applications (ConFoo YVR 2017)
Crafting Quality PHP Applications (ConFoo YVR 2017)
 
Cucumber Ru09 Web
Cucumber Ru09 WebCucumber Ru09 Web
Cucumber Ru09 Web
 
[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress Development[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress Development
 
jQuery
jQueryjQuery
jQuery
 
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
 
Scalable web application architecture
Scalable web application architectureScalable web application architecture
Scalable web application architecture
 
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
 
Django
DjangoDjango
Django
 
Webinar: AngularJS and the WordPress REST API
Webinar: AngularJS and the WordPress REST APIWebinar: AngularJS and the WordPress REST API
Webinar: AngularJS and the WordPress REST API
 
My app is secure... I think
My app is secure... I thinkMy app is secure... I think
My app is secure... I think
 
WCLV13 JavaScript
WCLV13 JavaScriptWCLV13 JavaScript
WCLV13 JavaScript
 
RSpec 2 Best practices
RSpec 2 Best practicesRSpec 2 Best practices
RSpec 2 Best practices
 
Broadleaf Presents Thymeleaf
Broadleaf Presents ThymeleafBroadleaf Presents Thymeleaf
Broadleaf Presents Thymeleaf
 
Keeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and Webpack
 
Ruby gems
Ruby gemsRuby gems
Ruby gems
 
Crafting Quality PHP Applications (PHP Benelux 2018)
Crafting Quality PHP Applications (PHP Benelux 2018)Crafting Quality PHP Applications (PHP Benelux 2018)
Crafting Quality PHP Applications (PHP Benelux 2018)
 
Beijing Perl Workshop 2008 Hiveminder Secret Sauce
Beijing Perl Workshop 2008 Hiveminder Secret SauceBeijing Perl Workshop 2008 Hiveminder Secret Sauce
Beijing Perl Workshop 2008 Hiveminder Secret Sauce
 
Thymeleaf Introduction
Thymeleaf IntroductionThymeleaf Introduction
Thymeleaf Introduction
 

Similar to Qpsmtpd

Modern Perl
Modern PerlModern Perl
Modern Perl
Dave Cross
 
PSGI and Plack from first principles
PSGI and Plack from first principlesPSGI and Plack from first principles
PSGI and Plack from first principles
Perl Careers
 
4.7 Automate Loading Data with Little to No Duplicates!
4.7 Automate Loading Data with Little to No Duplicates!4.7 Automate Loading Data with Little to No Duplicates!
4.7 Automate Loading Data with Little to No Duplicates!
TargetX
 
Optimizing AngularJS Application
Optimizing AngularJS ApplicationOptimizing AngularJS Application
Optimizing AngularJS Application
Md. Ziaul Haq
 
PHP SA 2014 - Releasing Your Open Source Project
PHP SA 2014 - Releasing Your Open Source ProjectPHP SA 2014 - Releasing Your Open Source Project
PHP SA 2014 - Releasing Your Open Source Project
xsist10
 
Modern Perl Web Development with Dancer
Modern Perl Web Development with DancerModern Perl Web Development with Dancer
Modern Perl Web Development with Dancer
Dave Cross
 
PerlDancer for Perlers (FOSDEM 2011)
PerlDancer for Perlers (FOSDEM 2011)PerlDancer for Perlers (FOSDEM 2011)
PerlDancer for Perlers (FOSDEM 2011)
xSawyer
 
Php on the Web and Desktop
Php on the Web and DesktopPhp on the Web and Desktop
Php on the Web and Desktop
Elizabeth Smith
 
PHP BASIC PRESENTATION
PHP BASIC PRESENTATIONPHP BASIC PRESENTATION
PHP BASIC PRESENTATION
krutitrivedi
 
Apache Dispatch
Apache DispatchApache Dispatch
Apache Dispatch
Fred Moyer
 
Building Better Applications with Data::Manager
Building Better Applications with Data::ManagerBuilding Better Applications with Data::Manager
Building Better Applications with Data::ManagerJay Shirley
 
Drupal 8 migrate!
Drupal 8 migrate!Drupal 8 migrate!
Drupal 8 migrate!
Pavel Makhrinsky
 
Mojolicious - A new hope
Mojolicious - A new hopeMojolicious - A new hope
Mojolicious - A new hope
Marcus Ramberg
 
SF Grails - Ratpack - Compact Groovy Webapps - James Williams
SF Grails - Ratpack - Compact Groovy Webapps - James WilliamsSF Grails - Ratpack - Compact Groovy Webapps - James Williams
SF Grails - Ratpack - Compact Groovy Webapps - James Williams
Philip Stehlik
 
Groovy On Trading Desk (2010)
Groovy On Trading Desk (2010)Groovy On Trading Desk (2010)
Groovy On Trading Desk (2010)
Jonathan Felch
 
My app is secure... I think
My app is secure... I thinkMy app is secure... I think
My app is secure... I think
Wim Godden
 
Creating a Mature Puppet System
Creating a Mature Puppet SystemCreating a Mature Puppet System
Creating a Mature Puppet System
Puppet
 

Similar to Qpsmtpd (20)

Modern Perl
Modern PerlModern Perl
Modern Perl
 
Mojolicious
MojoliciousMojolicious
Mojolicious
 
PSGI and Plack from first principles
PSGI and Plack from first principlesPSGI and Plack from first principles
PSGI and Plack from first principles
 
4.7 Automate Loading Data with Little to No Duplicates!
4.7 Automate Loading Data with Little to No Duplicates!4.7 Automate Loading Data with Little to No Duplicates!
4.7 Automate Loading Data with Little to No Duplicates!
 
Optimizing AngularJS Application
Optimizing AngularJS ApplicationOptimizing AngularJS Application
Optimizing AngularJS Application
 
PHP SA 2014 - Releasing Your Open Source Project
PHP SA 2014 - Releasing Your Open Source ProjectPHP SA 2014 - Releasing Your Open Source Project
PHP SA 2014 - Releasing Your Open Source Project
 
Modern Perl Web Development with Dancer
Modern Perl Web Development with DancerModern Perl Web Development with Dancer
Modern Perl Web Development with Dancer
 
PerlDancer for Perlers (FOSDEM 2011)
PerlDancer for Perlers (FOSDEM 2011)PerlDancer for Perlers (FOSDEM 2011)
PerlDancer for Perlers (FOSDEM 2011)
 
Php on the Web and Desktop
Php on the Web and DesktopPhp on the Web and Desktop
Php on the Web and Desktop
 
PHP BASIC PRESENTATION
PHP BASIC PRESENTATIONPHP BASIC PRESENTATION
PHP BASIC PRESENTATION
 
Apache Dispatch
Apache DispatchApache Dispatch
Apache Dispatch
 
Building Better Applications with Data::Manager
Building Better Applications with Data::ManagerBuilding Better Applications with Data::Manager
Building Better Applications with Data::Manager
 
Drupal 8 migrate!
Drupal 8 migrate!Drupal 8 migrate!
Drupal 8 migrate!
 
Mojolicious - A new hope
Mojolicious - A new hopeMojolicious - A new hope
Mojolicious - A new hope
 
SF Grails - Ratpack - Compact Groovy Webapps - James Williams
SF Grails - Ratpack - Compact Groovy Webapps - James WilliamsSF Grails - Ratpack - Compact Groovy Webapps - James Williams
SF Grails - Ratpack - Compact Groovy Webapps - James Williams
 
Tatsumaki
TatsumakiTatsumaki
Tatsumaki
 
Groovy On Trading Desk (2010)
Groovy On Trading Desk (2010)Groovy On Trading Desk (2010)
Groovy On Trading Desk (2010)
 
My app is secure... I think
My app is secure... I thinkMy app is secure... I think
My app is secure... I think
 
WordPress APIs
WordPress APIsWordPress APIs
WordPress APIs
 
Creating a Mature Puppet System
Creating a Mature Puppet SystemCreating a Mature Puppet System
Creating a Mature Puppet System
 

More from Fred Moyer

Reliable observability at scale: Error Budgets for 1,000+
Reliable observability at scale: Error Budgets for 1,000+Reliable observability at scale: Error Budgets for 1,000+
Reliable observability at scale: Error Budgets for 1,000+
Fred Moyer
 
Practical service level objectives with error budgeting
Practical service level objectives with error budgetingPractical service level objectives with error budgeting
Practical service level objectives with error budgeting
Fred Moyer
 
SREcon americas 2019 - Latency SLOs Done Right
SREcon americas 2019 - Latency SLOs Done RightSREcon americas 2019 - Latency SLOs Done Right
SREcon americas 2019 - Latency SLOs Done Right
Fred Moyer
 
Scale17x - Latency SLOs Done Right
Scale17x - Latency SLOs Done RightScale17x - Latency SLOs Done Right
Scale17x - Latency SLOs Done Right
Fred Moyer
 
Latency SLOs Done Right
Latency SLOs Done RightLatency SLOs Done Right
Latency SLOs Done Right
Fred Moyer
 
Latency SLOs done right
Latency SLOs done rightLatency SLOs done right
Latency SLOs done right
Fred Moyer
 
Comprehensive Container Based Service Monitoring with Kubernetes and Istio
Comprehensive Container Based Service Monitoring with Kubernetes and IstioComprehensive Container Based Service Monitoring with Kubernetes and Istio
Comprehensive Container Based Service Monitoring with Kubernetes and Istio
Fred Moyer
 
Comprehensive container based service monitoring with kubernetes and istio
Comprehensive container based service monitoring with kubernetes and istioComprehensive container based service monitoring with kubernetes and istio
Comprehensive container based service monitoring with kubernetes and istio
Fred Moyer
 
Effective management of high volume numeric data with histograms
Effective management of high volume numeric data with histogramsEffective management of high volume numeric data with histograms
Effective management of high volume numeric data with histograms
Fred Moyer
 
Statistics for dummies
Statistics for dummiesStatistics for dummies
Statistics for dummies
Fred Moyer
 
GrafanaCon EU 2018
GrafanaCon EU 2018GrafanaCon EU 2018
GrafanaCon EU 2018
Fred Moyer
 
Fredmoyer postgresopen 2017
Fredmoyer postgresopen 2017Fredmoyer postgresopen 2017
Fredmoyer postgresopen 2017
Fred Moyer
 
Better service monitoring through histograms sv perl 09012016
Better service monitoring through histograms sv perl 09012016Better service monitoring through histograms sv perl 09012016
Better service monitoring through histograms sv perl 09012016
Fred Moyer
 
Better service monitoring through histograms
Better service monitoring through histogramsBetter service monitoring through histograms
Better service monitoring through histograms
Fred Moyer
 
The Breakup - Logically Sharding a Growing PostgreSQL Database
The Breakup - Logically Sharding a Growing PostgreSQL DatabaseThe Breakup - Logically Sharding a Growing PostgreSQL Database
The Breakup - Logically Sharding a Growing PostgreSQL Database
Fred Moyer
 
Learning go for perl programmers
Learning go for perl programmersLearning go for perl programmers
Learning go for perl programmers
Fred Moyer
 
Surge 2012 fred_moyer_lightning
Surge 2012 fred_moyer_lightningSurge 2012 fred_moyer_lightning
Surge 2012 fred_moyer_lightning
Fred Moyer
 
Ball Of Mud Yapc 2008
Ball Of Mud Yapc 2008Ball Of Mud Yapc 2008
Ball Of Mud Yapc 2008
Fred Moyer
 
Data::FormValidator Simplified
Data::FormValidator SimplifiedData::FormValidator Simplified
Data::FormValidator Simplified
Fred Moyer
 

More from Fred Moyer (19)

Reliable observability at scale: Error Budgets for 1,000+
Reliable observability at scale: Error Budgets for 1,000+Reliable observability at scale: Error Budgets for 1,000+
Reliable observability at scale: Error Budgets for 1,000+
 
Practical service level objectives with error budgeting
Practical service level objectives with error budgetingPractical service level objectives with error budgeting
Practical service level objectives with error budgeting
 
SREcon americas 2019 - Latency SLOs Done Right
SREcon americas 2019 - Latency SLOs Done RightSREcon americas 2019 - Latency SLOs Done Right
SREcon americas 2019 - Latency SLOs Done Right
 
Scale17x - Latency SLOs Done Right
Scale17x - Latency SLOs Done RightScale17x - Latency SLOs Done Right
Scale17x - Latency SLOs Done Right
 
Latency SLOs Done Right
Latency SLOs Done RightLatency SLOs Done Right
Latency SLOs Done Right
 
Latency SLOs done right
Latency SLOs done rightLatency SLOs done right
Latency SLOs done right
 
Comprehensive Container Based Service Monitoring with Kubernetes and Istio
Comprehensive Container Based Service Monitoring with Kubernetes and IstioComprehensive Container Based Service Monitoring with Kubernetes and Istio
Comprehensive Container Based Service Monitoring with Kubernetes and Istio
 
Comprehensive container based service monitoring with kubernetes and istio
Comprehensive container based service monitoring with kubernetes and istioComprehensive container based service monitoring with kubernetes and istio
Comprehensive container based service monitoring with kubernetes and istio
 
Effective management of high volume numeric data with histograms
Effective management of high volume numeric data with histogramsEffective management of high volume numeric data with histograms
Effective management of high volume numeric data with histograms
 
Statistics for dummies
Statistics for dummiesStatistics for dummies
Statistics for dummies
 
GrafanaCon EU 2018
GrafanaCon EU 2018GrafanaCon EU 2018
GrafanaCon EU 2018
 
Fredmoyer postgresopen 2017
Fredmoyer postgresopen 2017Fredmoyer postgresopen 2017
Fredmoyer postgresopen 2017
 
Better service monitoring through histograms sv perl 09012016
Better service monitoring through histograms sv perl 09012016Better service monitoring through histograms sv perl 09012016
Better service monitoring through histograms sv perl 09012016
 
Better service monitoring through histograms
Better service monitoring through histogramsBetter service monitoring through histograms
Better service monitoring through histograms
 
The Breakup - Logically Sharding a Growing PostgreSQL Database
The Breakup - Logically Sharding a Growing PostgreSQL DatabaseThe Breakup - Logically Sharding a Growing PostgreSQL Database
The Breakup - Logically Sharding a Growing PostgreSQL Database
 
Learning go for perl programmers
Learning go for perl programmersLearning go for perl programmers
Learning go for perl programmers
 
Surge 2012 fred_moyer_lightning
Surge 2012 fred_moyer_lightningSurge 2012 fred_moyer_lightning
Surge 2012 fred_moyer_lightning
 
Ball Of Mud Yapc 2008
Ball Of Mud Yapc 2008Ball Of Mud Yapc 2008
Ball Of Mud Yapc 2008
 
Data::FormValidator Simplified
Data::FormValidator SimplifiedData::FormValidator Simplified
Data::FormValidator Simplified
 

Recently uploaded

Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
OnBoard
 
Pushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 daysPushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 days
Adtran
 
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptxSecstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
nkrafacyberclub
 
RESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for studentsRESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for students
KAMESHS29
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
DianaGray10
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
KatiaHIMEUR1
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
SOFTTECHHUB
 
By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024
Pierluigi Pugliese
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance
 
Free Complete Python - A step towards Data Science
Free Complete Python - A step towards Data ScienceFree Complete Python - A step towards Data Science
Free Complete Python - A step towards Data Science
RinaMondal9
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
Thijs Feryn
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
The Metaverse and AI: how can decision-makers harness the Metaverse for their...
The Metaverse and AI: how can decision-makers harness the Metaverse for their...The Metaverse and AI: how can decision-makers harness the Metaverse for their...
The Metaverse and AI: how can decision-makers harness the Metaverse for their...
Jen Stirrup
 
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdfSAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
Peter Spielvogel
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
Jemma Hussein Allen
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
Sri Ambati
 
Enhancing Performance with Globus and the Science DMZ
Enhancing Performance with Globus and the Science DMZEnhancing Performance with Globus and the Science DMZ
Enhancing Performance with Globus and the Science DMZ
Globus
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 

Recently uploaded (20)

Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
 
Pushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 daysPushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 days
 
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptxSecstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
 
RESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for studentsRESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for students
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
 
By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
 
Free Complete Python - A step towards Data Science
Free Complete Python - A step towards Data ScienceFree Complete Python - A step towards Data Science
Free Complete Python - A step towards Data Science
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
The Metaverse and AI: how can decision-makers harness the Metaverse for their...
The Metaverse and AI: how can decision-makers harness the Metaverse for their...The Metaverse and AI: how can decision-makers harness the Metaverse for their...
The Metaverse and AI: how can decision-makers harness the Metaverse for their...
 
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdfSAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
SAP Sapphire 2024 - ASUG301 building better apps with SAP Fiori.pdf
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
 
Enhancing Performance with Globus and the Science DMZ
Enhancing Performance with Globus and the Science DMZEnhancing Performance with Globus and the Science DMZ
Enhancing Performance with Globus and the Science DMZ
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 

Qpsmtpd

  • 1. Writing Applications with Qpsmtpd Fred Moyer fred@redhotpenguin.com
  • 2. Qpsmtpd ● Perl SMTP daemon written by Ask Bjørn Hansen ● “mod_perl” of smtp ● Plugin API makes writing extensions fun ● Works with Qmail, Postfix, and Exim ● Stock plugins include spam and virus protection ● If you've tried to extend a C based smtp daemon you've felt pain at some point
  • 3. Setting it up ● Read the article by Matt Sergeant [1] ● Install using RPMs if you can http://wiki.qpsmtpd.org/rpm-install_howto ● Installing from source is easy also http://wiki.qpsmtpd.org/quick-install_howto ● Telnetting to port 25 works for testing... ● SWAKS is your friend [3] ● qpsmtpd@perl.org is also your friend
  • 4. My config file /home/smtpd/qpsmtpd/config/plugins auth/auth_vpopmail_sql # set db auth in the plugin code denysoft_greylist redhotpenguin.com taperfriendlymusic.org quit_fortune check_earlytalker count_unrecognized_commands 4 check_relay # require_resolvable_fromhost # ^^ enable this to prevent zombies check_delivery normal 1 127.0.0.1 vppmail dbuser dbpass
  • 5. My config file /home/smtpd/qpsmtpd/config/plugins # rhsbl <- these blacklist plugins blacklist # dnsbl <- yahoo.com et al. sometimes! check_badmailfrom check_badrcptto check_spamhelo # sender_permitted_from rcpt_ok # this is the last rcpt plugin
  • 6. My config file /home/smtpd/qpsmtpd/config/plugins virus/klez_filter spamassassin reject_threshold 20 munge_subject_threshold 5 virus/clamav # here is my first qpsmtpd application craigslist recipient craig_qp@redhotpenguin.com site http://www.craigslist.org login fred@redhotpenguin.com password fredspass queue/qmail-queue # leave enabled to forward the email
  • 7. Many plugins available ● http://wiki.qpsmtpd.org/plugins ● Spam ● Virus ● Authentication – Vpopmail, PAM, text file, LDAP... ● Plugins are generally geared towards keeping the spam out, and letting the good mail through
  • 8. Your first plugin ● Start with good examples ● Read Matt Sergeant's O'reilly article [1] ● Read the source for existing plugins ● perldoc README.plugins ;)
  • 9. A simple subject filter ● Spam filters don't catch everything block_subject [ all | [ domain1, domain2 ... ] ] sub init { my ($self, $qp, @domains) = @_; unless (defined $domains[0]) { die “block_subject needs proper confign”; } $self->{_args}->{domains} = @domains; my $content = <<”SUBJECTS”; YOUR REPRESENTATIVE ASSISTANCE IS NEEDED Message From eBay Member The Ultimate Online Pharmaceutical SUBJECTS
  • 10. A simple subject filter my @subjects = split(“n”, $block_content); $self->{_args}->{subjects} = @subjects; $self->log(LOGDEBUG, “Blocking subjects $block_content”); } sub hook_data_post { my ($self, $transaction) = @_; if ($self->{_args}->{domains}->[0] eq 'all') { if ($self->_blocked_subject($transaction)) { return DENY; } } else {
  • 11. A simple subject filter # Check each domain my @recip_domains = map { $_->host } $transaction->recipients; foreach my $domain (@recip_domains) { # Deny the email if the subject is in our blacklist if (grep { $_ =~ m/^$domain$/ } @{$self->{_args}->{domains} && $self->blocked_subject($transaction)) { return DENY; } } } return DECLINED; }
  • 12. A simple subject filter sub blocked_subject { my ($self, $transaction) = @_; my $subject = $transaction->header->get('Subject'); chomp($subject); if (grep { $_ =~ m/$subject$/i } @{$self->{_args}->{subjects}}) { $self->log(LOGINFO, “block_subject invoked for $subject”); return 1; } return; }
  • 13. SMTP Applications? ● SMTP to HTTP Gateways ● Automate tedious processes ● Use emails to interact with applications ● Today's PDAs have IMAP based email but aren't very good at serving web pages
  • 14. A Practical Application ● The problem at hand ● A couple hundred things we couldn't sell ● Throwing away is bad for the environment (and costs money) ● http://www.craigslist.org - someone wants it ● But taking a picture of everything and posting an ad to Craigslist is a lot of clicking ● I don't like to click, I like to write Perl
  • 15. A Practical Application ● Possible solutions ● No internet connection ● I could make a list of the items at hand ● Call a friend and have him post ( no images though, and one less friend ) ● Or drive to local shop with wireless and click away
  • 16. A Practical Application ● My phone has a built in camera and email client ● I could take pictures and email them to myself with a description, and post from home ● That's repeating myself though, and too much work
  • 17. A Practical Application ● A Qpsmtpd plugin to solve this problem? ● It came down to being Lazy ● Being able to post an item at will is preferable to batching transactions ● Bonus points for a per item picture, response rates for items with pictures are much higher than without
  • 18. A Waste of Time? ● At 3 minutes overhead per item the transaction overhead is 7.5 hours for 150 items ● At 30 seconds overhead per item the transaction overhead is 75 minutes for 150 items ● Total time spent thinking, coding, testing and deploying was about 3 hours ● Bonus points for writing fun code!
  • 19. The Source ● Initialization use WWW::Mechanize; use Data::Dumper; sub init { my ($self, $qp, %args) = @_; $self->{_args} = %args; $self->{_mech} = WWW::Mechanize->new; $self->log(LOGDEBUG, “Craigslist plugin init: n” . Dumper(%args)); }
  • 20. The Source ● Start processing after all data is received ● Check authorization first sub hook_data_post { my ($self, $transaction) = @_; return DECLINED unless (($transaction->recipients->[0]->address eq $self->{_args}->{recipient}) && $self->qp->connection->relay_client);
  • 21. The Source ● Get the subject and body my $subject = $transaction->header->get('Subject'); my $body; while ( my $line = $transaction->body_getline ) { $body .= $line; } use Email::MIME; my $em = Email::MIME->new($subject . $body);
  • 22. The Source ● Get the attached images and save them use Email::MIME::Attachment::Stripper; my $stripper = Email::MIME::Attachment::Stripper->new($em); my $attachments = $stripper->attachments; if (@attachments) { foreach my $at (@attachments) { my $fh; open($fh, “>”, “/tmp/” . $at->{filename}) || die $!; print $fh $at->{payload}; close($fh); } }
  • 23. The Source ● Login to http://www.craigslist.org $self->{_mech}->get($self->{_args}->{site}); $self->{_mech}->submit_form( form_name => “login”, fields => { inputEmailHandle => $self->{_args}->{login}, inputPassword => $self->{_args}->{password} }); if (! $self->{_mech}->success ) { $transaction->body_write(“Error during login”); return DECLINED; }
  • 24. The Source ● Login to www.craigslist.org $self->{_mech}->get($self->{_args}->{site}); $self->{_mech}->submit_form( form_name => “login”, fields => { inputEmailHandle => $self->{_args}->{login}, inputPassword => $self->{_args}->{password} }); if (! $self->{_mech}->success ) { $transaction->body_write(“Error during login”); return DECLINED; }
  • 25. The Source ● Walk the website $self->{_mech}->follow_link( text_regex => qr/wanted/ ); if (! $self->{_mech}->success ) { $transaction->body_write(“Error following wanted link”); return DECLINED; } # ... click through a few more links to get to ad posting
  • 26. The Source ● Post the ad $self->{_mech}->submit_form( form_number => 1, button => 'imagesForm', fields => { PostingTitle => $subject, PostingBody => $body, Ask => 0, }); if (! $self->{_mech}->success) { $transaction->body_write(“Error, could not post ad”); return DECLINED; }
  • 27. The Source ● Post the images foreach my $at (@attachments) { $self->{_mech}->submit_form( form_number => 1, fields => { file1 => '/tmp/' . $at->{filename} } ); if (! $self->{_mech}->success) { $transaction->write_body( “Error adding image “ . $at->{filename}); return DECLINED; } unlink('/tmp/' . $at->{filename}); }
  • 28. We're done ● Grab the PDA ● Take a picture ● Compose an email ● Receive a flood of responses ( still need to write that part of the app )
  • 29. Perl did the work ● No clicking (except taking the photo) ● No dealing with a cumbersome web based application ● Our energy goes to where it's needed most ● All we had to do was code up a defined process
  • 30. Recommended API Practices ● Run your application last after all other plugins, before the queue plugin ● Forward the email to the sender as a receipt ● Use a separate To: address for each app, one that isn't vulnerable to dictionary attacks
  • 31. Giving feedback to the User ● Indicate success or failure ● Let them know why it failed - $transaction->write_body(“Why it failed”); ● Be strict in what you accept – the spammers will find your openings eventually
  • 32. Recommended AAA Approaches ● Require users to authenticate via SMTP auth - as secure as normal SMTP transactions $self->qp->connection->relay_client == 1 ● Combine username with To: address and match that against sender address, fairly secure but not unbreakable To: fred_craigslist@domain.com, From: fred@fredsdomain.com ● Greylisting can help here but remember that zombies can retry with dictionary attacks
  • 33. Recommended AAA Approaches ● Require the user register their email address and verify they are a real person ● Don't use a password in the email - most users have one password and will blissfully use it here as well ● Use good judgement in weighing ease of use vs. security in authentication – err on the side of security.
  • 34. Recommended AAA Approaches ● Don't use this approach to build secure apps unless you _really_ know what you are doing. Better yet, just don't do it. ● Don't send sensitive information in plain text email ● This approach is about making automated tasks easy from insecure clients (PDAs). Proceed as such.
  • 35. More Ideas ● Reply to those annoying “DO NOT REPLY” emails from Bugzilla, et al. ● Check the weather ● Check the traffic report ● Next bus ● Post to a picture blog from your PDA ● Any process that is repeatable and boring
  • 36. Credits ● The Qpsmtpd community ● Ask Bjørn Hansen for authoring Qpsmtpd ● Matt Sergeant and Robert Spier for listening to my crazy ideas on #qpsmtpd
  • 37. References [1] – Using Qpsmtpd, Matt Sergeant http://www.oreillynet.com/pub/a/sysadmin/2005/09/15/qpsmtpd.html [2] – The Qpsmtpd Wiki http://wiki.qpsmtpd.org [3] – SWAKS http://jetmore.org/john/code/#swaks
  • 38. Slides These slides are freely available at http://www.redhotpenguin.com/talks Thank you NPW 2006!