SlideShare une entreprise Scribd logo
1  sur  107
Télécharger pour lire hors ligne
the 2009 PEP talk!!!
...I work there!
YAPC::NA 2006
PEP: Thoughts from Pobox
        YAPC::NA 2006
YAPC::NA 2007
How I Learned To
Stop Worrying and Love Email
          YAPC::NA 2007
YAPC::NA 2008
Email
hates the living!
      YAPC::NA 2008
What’s the best way to
deal with horrible code?
Write more code!


...so I did! The last year has been really productive. Lots of obnoxious problems were sorted out. I’m
really happy with what we got accomplished, and so finally I can with a straight face...
rjbs
               <3
             email
the 2009 PEP talk!!!
sending email
MIME::Lite
                       Mail::Send
                      Mail::Sender
                      Mail::Sendmail

so, here are some of the libraries for sending mail. these all let you specify subject, to/from, and
content -- so you can’t actually make an email just hwo you want and pass it in. worthless for any real
use
Mail::Mailer


this lets you send mail through pluggable backends, and you provide the mail message. not bad, but
not great; it has this weird API where it isa IO::Handle and you print to it like a filehandle to send your
message. subclassing is a pain because it’s a blessed globref
Email::Send


Email::Send simplifies by expecting a string, being a hashref, and being in theory easier to extend (by
using Module::Pluggable)
unfortunately, this pluggability (and some other oddities) ends up making extending things harder and
can cause it to silently lose mail. for real.
this is probably about about as good as a number of them.
system(“sendmail @opts < $tempfile”)
         && die sprintf “sendmail died: %s”, errstr($?);




this is probably about about as good as a number of them.
Mail::Transport


So, Mail::Transport isn’t bad. It’s part of the Mail-Box distro, which means it tends to get things right,
but it also tends to be confusing and overwhelming for new users. If you’re already using it happily,
that’s great! We weren’t, though, and so we wrote something new, built using just the ideas we liked
from Email::Send, and
Email::Sender
Email::Sender
Email::Sender

Email-Sender uses Møøse
Email::Sender

Email-Sender uses Møøse
Email::Sender is a role
Email::Sender

Email-Sender uses Møøse
Email::Sender is a role
you use Email::Sender::Simple
Email::Sender::Simple


              use Email::Sender::Simple qw(sendmail);

              my $email = $customer->build_welcome_email;

              sendmail($email);




Yup. That’s about it. That will try to send mail with either sendmail or SMTP, depending on what’s
available. If it can’t send the message, it will throw.
Email::Sender::Simple
              use Email::Sender::Simple qw(sendmail);

              my $email = $customer->build_welcome_email;

              sendmail(
               $email,
               {
                 to    => @rcpts,
                 from => $sender,
               }
              );




In other words, you can specify the envelope separately from the header. This is of *vital* importance
to real email work. VERP, mailing lists, especially.
Email::Sender::Simple

         my $smtp = Email::Sender::Transport::SMTP->new({
           host => ‘sasl.pobox.com’,
           port => 26,
         });

         sendmail($email, { transport => $smtp });




If you don’t like the auto-detected transport, you can specify one. Transports are really easy to write,
and a bunch already exist:
Transports




SQLite is especially handy because you can dump all mail from a forking program into an easy-to-test
database.
Transports
                Sendmail




SQLite is especially handy because you can dump all mail from a forking program into an easy-to-test
database.
Transports
                Sendmail
                SMTP




SQLite is especially handy because you can dump all mail from a forking program into an easy-to-test
database.
Transports
                Sendmail
                SMTP
                Persist. SMTP




SQLite is especially handy because you can dump all mail from a forking program into an easy-to-test
database.
Transports
                Sendmail
                SMTP
                Persist. SMTP
                Maildir, Mbox


SQLite is especially handy because you can dump all mail from a forking program into an easy-to-test
database.
Transports
                Sendmail                                   DevNull
                SMTP
                Persist. SMTP
                Maildir, Mbox


SQLite is especially handy because you can dump all mail from a forking program into an easy-to-test
database.
Transports
                Sendmail                                   DevNull
                SMTP                                       Print
                Persist. SMTP
                Maildir, Mbox


SQLite is especially handy because you can dump all mail from a forking program into an easy-to-test
database.
Transports
                Sendmail                                   DevNull
                SMTP                                       Print
                Persist. SMTP                              Test
                Maildir, Mbox


SQLite is especially handy because you can dump all mail from a forking program into an easy-to-test
database.
Transports
                Sendmail                                   DevNull
                SMTP                                       Print
                Persist. SMTP                              Test
                Maildir, Mbox                              SQLite


SQLite is especially handy because you can dump all mail from a forking program into an easy-to-test
database.
Email::Sender::Simple

         my $smtp = Email::Sender::Transport::SMTP->new({
           host => ‘sasl.pobox.com’,
           port => 26,
         });

         sendmail($email, { transport => $smtp });




so, you can do this, that’s fine, and you can use any of those cool transports when you call sendmail...
but what about if you want to change the whole default?
Email::Sender::Simple


         walrus!rjbs:~$ EMAIL_SENDER_TRANSPORT=Maildir
           my-awesome-program --auden




now *every* call to Email::Sender::Simple->send will deliver to ./Maildir so you can see exactly what it
would have sent
Programmable Failure




so, for example, we have a system that distributes mail across a cluster of hosts with various
mechanisms to cope with failure

Failable lets me test them by using a mailer that always works wrapped in predictable failure, easily
Programmable Failure

                 ::Failable transport




so, for example, we have a system that distributes mail across a cluster of hosts with various
mechanisms to cope with failure

Failable lets me test them by using a mailer that always works wrapped in predictable failure, easily
Programmable Failure

                 ::Failable transport
                 wrap any transport




so, for example, we have a system that distributes mail across a cluster of hosts with various
mechanisms to cope with failure

Failable lets me test them by using a mailer that always works wrapped in predictable failure, easily
Programmable Failure

                 ::Failable transport
                 wrap any transport
                 make it fail when you want


so, for example, we have a system that distributes mail across a cluster of hosts with various
mechanisms to cope with failure

Failable lets me test them by using a mailer that always works wrapped in predictable failure, easily
Other Random Senderisms
Other Random Senderisms


  structured failure
Other Random Senderisms


  structured failure
  partial successes
making email messages
Email::Simple
Email::MIME
these are pretty low level
you probably want to
send only a few messages
  (but with differences)
MIME Crap to Deal With
MIME Crap to Deal With

 header encoding
MIME Crap to Deal With

 header encoding
 content encoding
MIME Crap to Deal With

 header encoding
 content encoding
 building html & plain parts
MIME Crap to Deal With

 header encoding
 content encoding
 building html & plain parts
 attaching files
Other Crap to Deal With
Other Crap to Deal With

 templated documents
Other Crap to Deal With

 templated documents
 validate parameters
Other Crap to Deal With

 templated documents
 validate parameters
 reusable hunks of content
hate!
Existing Solutions
Existing Solutions
none?
Existing Solutions
none?
horrible hacks
Existing Solutions
none?
horrible hacks
 make a template in TT
Existing Solutions
none?
horrible hacks
 make a template in TT
 render to html
Existing Solutions
none?
horrible hacks
 make a template in TT
 render to html
 html-to-text
Existing Solutions
none?
horrible hacks
 make a template in TT
 render to html
 html-to-text
 hope you guess right at headers
Email::MIME::Kit
Email::MIME::Kit
Email::MIME::Kit

a bunch of files
Email::MIME::Kit

a bunch of files
with instructions on how to
assemble them
Email::MIME::Kit

a bunch of files
with instructions on how to
assemble them
and some other data
Kit Manifest
{
    "renderer" : "TT",
    "header"     : [
       { "Subject": "Hello [% user.name %]"        },
       { "From":     "Test Sender <test@test.com>" },
       { "To":       "[% user.email %]"            }
    ],
    "alternatives": [
       { "type": "text/plain", "path": "body.txt" },
       { "type": "text/html", "path": "body.html" }
    ],
    "attachments": [
       { "path": "demands.rtf" }
    ]
}
Assembling the Kit


my $kit = Email::MIME::Kit->new({ source => ‘msg.mkit’ });

my $email = $kit->assemble({ user => $user_object });

sendmail($email);
Dear ,

              Thank you for being a customer since .

              Your account has been due to . Please
              contact before at or we will be forced
              to your lovely wife Tracy’s head.

              Cheers,
              Anonymous




Ugh. Our $user_object was undef. Now we get crap that looks like mail but stinks and makes us look
like idiots.

We can plug in a validator pretty easily, though...
Kit Manifest
{
    "renderer" : "TT",
    “validator”: “Rx”,
    "header"     : [
       { "Subject": "Hello [% user.name %]"        },
       { "From":     "Test Sender <test@test.com>" },
       { "To":       "[% user.email %]"            }
    ],
    "alternatives": [
       { "type": "text/plain", "path": "body.txt" },
       { "type": "text/html", "path": "body.html" }
    ],
    "attachments": [
       { "path": "demands.rtf" }
    ]
}
rx.json

{
    “type”: “//rec”,
    “required”: {
      “user”: {
        “type”: “/perl/obj”,
        “isa” : “User::Account”
      }
    }
}
Assembling the Kit

my $kit = Email::MIME::Kit->new({ source => ‘msg.mkit’ });

my $email = $kit->assemble({ user => undef });

undefined value
  tag: [ “/err/nil” ],
  data path: [ “user” ],
  schema path: [ “user” ]
at slide 42, line 3
Annoying Crap: Dealt With
Annoying Crap: Dealt With
  if user.name is Ævar...
Annoying Crap: Dealt With
  if user.name is Ævar...
  if attachments are binary...
Annoying Crap: Dealt With
  if user.name is Ævar...
  if attachments are binary...
  text-only (singlepart) mail...
Annoying Crap: Dealt With
  if user.name is Ævar...
  if attachments are binary...
  text-only (singlepart) mail...
  HTML with images as
  attachments...
...so what’s still annoying?
Some Kits...




so, you love mkits and you’re writing them all the time... now you start having this problem...
Some Kits...
          ./body.html
          ./body.txt
          ./logo.jpg
          ./background.jpg
          ./manifest.json




so, you love mkits and you’re writing them all the time... now you start having this problem...
Some Kits...
          ./body.html                                   ./body.html
          ./body.txt                                    ./body.txt
          ./logo.jpg                                    ./logo.jpg
          ./background.jpg                              ./background.jpg
          ./manifest.json                               ./manifest.json




so, you love mkits and you’re writing them all the time... now you start having this problem...
Some Kits...
          ./body.html                                   ./body.html
          ./body.txt                                    ./body.txt
          ./logo.jpg                                    ./logo.jpg
          ./background.jpg                              ./background.jpg
          ./manifest.json                               ./manifest.json




       ./body.html
       ./body.txt
       ./logo.jpg
       ./background.jpg
       ./manifest.json




so, you love mkits and you’re writing them all the time... now you start having this problem...
Some Kits...
          ./body.html                                   ./body.html
          ./body.txt                                    ./body.txt
          ./logo.jpg                                    ./logo.jpg
          ./background.jpg                              ./background.jpg
          ./manifest.json                               ./manifest.json




       ./body.html                                      ./body.html
       ./body.txt                                       ./body.txt
       ./logo.jpg                                       ./logo.jpg
       ./background.jpg                                 ./background.jpg
       ./manifest.json                                  ./manifest.json




so, you love mkits and you’re writing them all the time... now you start having this problem...
Some Kits...
          ./body.html                                 ./body.html
          ./body.txt                                  ./body.txt
          ./logo.jpg                                  ./logo.jpg
          ./background.jpg                            ./background.jpg
          ./manifest.json                             ./manifest.json




       ./body.html                                    ./body.html
       ./body.txt                                     ./body.txt
       ./logo.jpg                                     ./logo.jpg
       ./background.jpg                               ./background.jpg
       ./manifest.json                                ./manifest.json




those files are identical everywhere. blaugh! duplication baaaaaaaaaad
The Kit Reader
The Kit Reader

EMKit gets at its contents
with the kit reader
The Kit Reader

EMKit gets at its contents
with the kit reader
normally, just looks for files
in the kit directory
SWAK!




/fs    (can be chrooted)
/dist
/kit (default, too)
SWAK!

         you can write your own kit reader




/fs    (can be chrooted)
/dist
/kit (default, too)
SWAK!

         you can write your own kit reader
         SWAK: Path::Resolver




/fs    (can be chrooted)
/dist
/kit (default, too)
SWAK!

         you can write your own kit reader
         SWAK: Path::Resolver

                           /kit/body.html




/fs    (can be chrooted)
/dist
/kit (default, too)
SWAK!

         you can write your own kit reader
         SWAK: Path::Resolver

                           /kit/body.html
                           body.html




/fs    (can be chrooted)
/dist
/kit (default, too)
SWAK!

         you can write your own kit reader
         SWAK: Path::Resolver

                           /kit/body.html
                           body.html
                           /fs/usr/share/app/body.html




/fs    (can be chrooted)
/dist
/kit (default, too)
SWAK in Use
       ./body.html
       ./body.txt
       ./manifest.json



       ./body.html
       ./body.txt
       ./manifest.json



       ./body.html
       ./body.txt
       ./manifest.json




So, we can take those common files and put them in our dist’s shared resources, and reference them
with the “/dist/” prefix, which finds stuff in share-dirs.

So, awesome! What’s still annoying?
SWAK in Use
       ./body.html
       ./body.txt
       ./manifest.json



       ./body.html                                   /dist/YourApp/logo.jpg
                                                     /dist/YourApp/background.jpg
       ./body.txt
       ./manifest.json



       ./body.html
       ./body.txt
       ./manifest.json




So, we can take those common files and put them in our dist’s shared resources, and reference them
with the “/dist/” prefix, which finds stuff in share-dirs.

So, awesome! What’s still annoying?
SWAK in Use
       ./body.html
       ./body.txt
       ./manifest.json



       ./body.html                                       /dist/YourApp/logo.jpg
                                                         /dist/YourApp/background.jpg
       ./body.txt
       ./manifest.json



       ./body.html
       ./body.txt
       ./manifest.json




almost certainly, the html and text parts are (a) really close to each other within one kit (b) contain
really different parts between kits (c) contain common boilerplate between kits
EMK::Assembler::Markdown
       ./body.mkdn
       ./manifest.json


                                                       /dist/YourApp/logo.jpg
                                                       /dist/YourApp/background.jpg
       ./body.mkdn
       ./manifest.json




       ./body.mkdn
       ./manifest.json




So, let’s fix that, too. We replace the text and html parts with a single Markdown document. We’ll use
the Markdown itself for the plaintext part and we’ll turn it into HTML to use in the HTML part.

Of course, this still needs work. We want wrapper stuff and copyright and so on in both parts.
EMK::Assembler::Markdown
./body.mkdn
./manifest.json


                  /dist/YourApp/logo.jpg
                  /dist/YourApp/background.jpg
./body.mkdn       /dist/YourApp/wrapper.html
./manifest.json   /dist/YourApp/wrapper.text




./body.mkdn
./manifest.json
Thank you!

Contenu connexe

Tendances

StormMQ Introduction to AMQP, Dublin
StormMQ Introduction to AMQP, DublinStormMQ Introduction to AMQP, Dublin
StormMQ Introduction to AMQP, DublinStormMQ
 
24 Hours Of Exchange Server 2007 ( Part 9 Of 24)
24  Hours Of  Exchange  Server 2007 ( Part 9 Of 24)24  Hours Of  Exchange  Server 2007 ( Part 9 Of 24)
24 Hours Of Exchange Server 2007 ( Part 9 Of 24)Harold Wong
 
An Introduction to AMQP with Code Samples
An Introduction to AMQP with Code SamplesAn Introduction to AMQP with Code Samples
An Introduction to AMQP with Code SamplesStormMQ
 
NATS + Docker meetup talk Oct - 2016
NATS + Docker meetup talk Oct - 2016NATS + Docker meetup talk Oct - 2016
NATS + Docker meetup talk Oct - 2016wallyqs
 
Better CSV processing with Ruby 2.6
Better CSV processing with Ruby 2.6Better CSV processing with Ruby 2.6
Better CSV processing with Ruby 2.6Kouhei Sutou
 
Kafka zero to hero
Kafka zero to heroKafka zero to hero
Kafka zero to heroAvi Levi
 
Queues queues queues — How RabbitMQ enables reactive architectures
Queues queues queues — How RabbitMQ enables reactive architecturesQueues queues queues — How RabbitMQ enables reactive architectures
Queues queues queues — How RabbitMQ enables reactive architecturesMartin Tajur
 
Groovy example in mule
Groovy example in muleGroovy example in mule
Groovy example in muleMohammed246
 
Unit 59 diary
Unit 59 diaryUnit 59 diary
Unit 59 diaryinwill12
 
Codefresh + BlazeMeter Webinar: Continuous Testing for Containerized Applicat...
Codefresh + BlazeMeter Webinar: Continuous Testing for Containerized Applicat...Codefresh + BlazeMeter Webinar: Continuous Testing for Containerized Applicat...
Codefresh + BlazeMeter Webinar: Continuous Testing for Containerized Applicat...Brittany Ingram
 
Using message enricher
Using message enricherUsing message enricher
Using message enricherSon Nguyen
 
GopherFest 2017 - Adding Context to NATS
GopherFest 2017 -  Adding Context to NATSGopherFest 2017 -  Adding Context to NATS
GopherFest 2017 - Adding Context to NATSwallyqs
 
The Real Time Web with XMPP
The Real Time Web with XMPPThe Real Time Web with XMPP
The Real Time Web with XMPPJack Moffitt
 
Rabbitmq, amqp Intro - Messaging Patterns
Rabbitmq, amqp Intro - Messaging PatternsRabbitmq, amqp Intro - Messaging Patterns
Rabbitmq, amqp Intro - Messaging PatternsJavier Arias Losada
 
Implementing WebServices with Camel and CXF in ServiceMix
Implementing WebServices with Camel and CXF in ServiceMixImplementing WebServices with Camel and CXF in ServiceMix
Implementing WebServices with Camel and CXF in ServiceMixAdrian Trenaman
 

Tendances (20)

StormMQ Introduction to AMQP, Dublin
StormMQ Introduction to AMQP, DublinStormMQ Introduction to AMQP, Dublin
StormMQ Introduction to AMQP, Dublin
 
24 Hours Of Exchange Server 2007 ( Part 9 Of 24)
24  Hours Of  Exchange  Server 2007 ( Part 9 Of 24)24  Hours Of  Exchange  Server 2007 ( Part 9 Of 24)
24 Hours Of Exchange Server 2007 ( Part 9 Of 24)
 
An Introduction to AMQP with Code Samples
An Introduction to AMQP with Code SamplesAn Introduction to AMQP with Code Samples
An Introduction to AMQP with Code Samples
 
NATS + Docker meetup talk Oct - 2016
NATS + Docker meetup talk Oct - 2016NATS + Docker meetup talk Oct - 2016
NATS + Docker meetup talk Oct - 2016
 
Better CSV processing with Ruby 2.6
Better CSV processing with Ruby 2.6Better CSV processing with Ruby 2.6
Better CSV processing with Ruby 2.6
 
Kafka zero to hero
Kafka zero to heroKafka zero to hero
Kafka zero to hero
 
Queues queues queues — How RabbitMQ enables reactive architectures
Queues queues queues — How RabbitMQ enables reactive architecturesQueues queues queues — How RabbitMQ enables reactive architectures
Queues queues queues — How RabbitMQ enables reactive architectures
 
Art Of Message Queues
Art Of Message QueuesArt Of Message Queues
Art Of Message Queues
 
Apache Kafka Demo
Apache Kafka DemoApache Kafka Demo
Apache Kafka Demo
 
Kafka tutorial
Kafka tutorialKafka tutorial
Kafka tutorial
 
Groovy example in mule
Groovy example in muleGroovy example in mule
Groovy example in mule
 
Unit 59 diary
Unit 59 diaryUnit 59 diary
Unit 59 diary
 
Codefresh + BlazeMeter Webinar: Continuous Testing for Containerized Applicat...
Codefresh + BlazeMeter Webinar: Continuous Testing for Containerized Applicat...Codefresh + BlazeMeter Webinar: Continuous Testing for Containerized Applicat...
Codefresh + BlazeMeter Webinar: Continuous Testing for Containerized Applicat...
 
Using message enricher
Using message enricherUsing message enricher
Using message enricher
 
Apache kafka
Apache kafkaApache kafka
Apache kafka
 
Apache kafka
Apache kafkaApache kafka
Apache kafka
 
GopherFest 2017 - Adding Context to NATS
GopherFest 2017 -  Adding Context to NATSGopherFest 2017 -  Adding Context to NATS
GopherFest 2017 - Adding Context to NATS
 
The Real Time Web with XMPP
The Real Time Web with XMPPThe Real Time Web with XMPP
The Real Time Web with XMPP
 
Rabbitmq, amqp Intro - Messaging Patterns
Rabbitmq, amqp Intro - Messaging PatternsRabbitmq, amqp Intro - Messaging Patterns
Rabbitmq, amqp Intro - Messaging Patterns
 
Implementing WebServices with Camel and CXF in ServiceMix
Implementing WebServices with Camel and CXF in ServiceMixImplementing WebServices with Camel and CXF in ServiceMix
Implementing WebServices with Camel and CXF in ServiceMix
 

Similaire à i &lt;3 email

How to simplify Email oriented workflow with - Visendo SMTP Extender
How to simplify Email oriented workflow with - Visendo SMTP Extender How to simplify Email oriented workflow with - Visendo SMTP Extender
How to simplify Email oriented workflow with - Visendo SMTP Extender Johannes Cosmin dumitru
 
Send email attachment using smtp in mule esb
Send email attachment using smtp in mule esbSend email attachment using smtp in mule esb
Send email attachment using smtp in mule esbSreekanth Kondapalli
 
Email/Ad/Marketing 20100130
Email/Ad/Marketing 20100130Email/Ad/Marketing 20100130
Email/Ad/Marketing 20100130dsoprea
 
Send email attachment using smtp in mule esb
Send email attachment using smtp in mule esbSend email attachment using smtp in mule esb
Send email attachment using smtp in mule esbRaviShankar Mishra
 
10135 a 05
10135 a 0510135 a 05
10135 a 05Bố Su
 
Scanned by CamScannerModule 03 Lab WorksheetWeb Developmen.docx
Scanned by CamScannerModule 03 Lab WorksheetWeb Developmen.docxScanned by CamScannerModule 03 Lab WorksheetWeb Developmen.docx
Scanned by CamScannerModule 03 Lab WorksheetWeb Developmen.docxanhlodge
 
Send email attachment using smtp in mule esb
Send email attachment using smtp in mule esbSend email attachment using smtp in mule esb
Send email attachment using smtp in mule esbPraneethchampion
 
Send email attachment using smtp in mule esb
Send email attachment using smtp  in mule esbSend email attachment using smtp  in mule esb
Send email attachment using smtp in mule esbPhaniu
 
Send email attachment using smtp in mule esb
Send email attachment using smtp  in mule esbSend email attachment using smtp  in mule esb
Send email attachment using smtp in mule esbirfan1008
 
Send email attachment using smtp in mule esb
Send email attachment using smtp  in mule esbSend email attachment using smtp  in mule esb
Send email attachment using smtp in mule esbprinceirfancivil
 
vishal_sharma: python email sending software
vishal_sharma: python email sending software  vishal_sharma: python email sending software
vishal_sharma: python email sending software vishal sharma
 
window server 2008 mail configuration
window server 2008 mail configurationwindow server 2008 mail configuration
window server 2008 mail configurationanwarkade1
 

Similaire à i &lt;3 email (20)

Linux10 sendmail
Linux10 sendmailLinux10 sendmail
Linux10 sendmail
 
Mail
MailMail
Mail
 
How to simplify Email oriented workflow with - Visendo SMTP Extender
How to simplify Email oriented workflow with - Visendo SMTP Extender How to simplify Email oriented workflow with - Visendo SMTP Extender
How to simplify Email oriented workflow with - Visendo SMTP Extender
 
Send email attachment using smtp in mule esb
Send email attachment using smtp in mule esbSend email attachment using smtp in mule esb
Send email attachment using smtp in mule esb
 
Mail
MailMail
Mail
 
Send Email In Asp.Net
Send Email In Asp.NetSend Email In Asp.Net
Send Email In Asp.Net
 
Email/Ad/Marketing 20100130
Email/Ad/Marketing 20100130Email/Ad/Marketing 20100130
Email/Ad/Marketing 20100130
 
Send email attachment using smtp in mule esb
Send email attachment using smtp in mule esbSend email attachment using smtp in mule esb
Send email attachment using smtp in mule esb
 
Mail server
Mail serverMail server
Mail server
 
Mail server
Mail serverMail server
Mail server
 
10135 a 05
10135 a 0510135 a 05
10135 a 05
 
pop3-imap.ppt
pop3-imap.pptpop3-imap.ppt
pop3-imap.ppt
 
pop3-imap.ppt
pop3-imap.pptpop3-imap.ppt
pop3-imap.ppt
 
Scanned by CamScannerModule 03 Lab WorksheetWeb Developmen.docx
Scanned by CamScannerModule 03 Lab WorksheetWeb Developmen.docxScanned by CamScannerModule 03 Lab WorksheetWeb Developmen.docx
Scanned by CamScannerModule 03 Lab WorksheetWeb Developmen.docx
 
Send email attachment using smtp in mule esb
Send email attachment using smtp in mule esbSend email attachment using smtp in mule esb
Send email attachment using smtp in mule esb
 
Send email attachment using smtp in mule esb
Send email attachment using smtp  in mule esbSend email attachment using smtp  in mule esb
Send email attachment using smtp in mule esb
 
Send email attachment using smtp in mule esb
Send email attachment using smtp  in mule esbSend email attachment using smtp  in mule esb
Send email attachment using smtp in mule esb
 
Send email attachment using smtp in mule esb
Send email attachment using smtp  in mule esbSend email attachment using smtp  in mule esb
Send email attachment using smtp in mule esb
 
vishal_sharma: python email sending software
vishal_sharma: python email sending software  vishal_sharma: python email sending software
vishal_sharma: python email sending software
 
window server 2008 mail configuration
window server 2008 mail configurationwindow server 2008 mail configuration
window server 2008 mail configuration
 

Plus de Ricardo Signes

Perl 5: Today, Tomorrow, and Christmas
Perl 5: Today, Tomorrow, and ChristmasPerl 5: Today, Tomorrow, and Christmas
Perl 5: Today, Tomorrow, and ChristmasRicardo Signes
 
What's New in Perl? v5.10 - v5.16
What's New in Perl?  v5.10 - v5.16What's New in Perl?  v5.10 - v5.16
What's New in Perl? v5.10 - v5.16Ricardo Signes
 
Perl 5.14 for Pragmatists
Perl 5.14 for PragmatistsPerl 5.14 for Pragmatists
Perl 5.14 for PragmatistsRicardo Signes
 
Dist::Zilla - Maximum Overkill for CPAN Distributions
Dist::Zilla - Maximum Overkill for CPAN DistributionsDist::Zilla - Maximum Overkill for CPAN Distributions
Dist::Zilla - Maximum Overkill for CPAN DistributionsRicardo Signes
 
Perl 5.12 for Everyday Use
Perl 5.12 for Everyday UsePerl 5.12 for Everyday Use
Perl 5.12 for Everyday UseRicardo Signes
 
Antediluvian Unix: A Guide to Unix Fundamentals
Antediluvian Unix: A Guide to Unix FundamentalsAntediluvian Unix: A Guide to Unix Fundamentals
Antediluvian Unix: A Guide to Unix FundamentalsRicardo Signes
 
Perl 5.10 for People Who Aren't Totally Insane
Perl 5.10 for People Who Aren't Totally InsanePerl 5.10 for People Who Aren't Totally Insane
Perl 5.10 for People Who Aren't Totally InsaneRicardo Signes
 
Writing Modular Command-line Apps with App::Cmd
Writing Modular Command-line Apps with App::CmdWriting Modular Command-line Apps with App::Cmd
Writing Modular Command-line Apps with App::CmdRicardo Signes
 
Crafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::ExporterCrafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::ExporterRicardo Signes
 
How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!
How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!
How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!Ricardo Signes
 

Plus de Ricardo Signes (11)

Perl 5: Today, Tomorrow, and Christmas
Perl 5: Today, Tomorrow, and ChristmasPerl 5: Today, Tomorrow, and Christmas
Perl 5: Today, Tomorrow, and Christmas
 
What's New in Perl? v5.10 - v5.16
What's New in Perl?  v5.10 - v5.16What's New in Perl?  v5.10 - v5.16
What's New in Perl? v5.10 - v5.16
 
Perl 5.14 for Pragmatists
Perl 5.14 for PragmatistsPerl 5.14 for Pragmatists
Perl 5.14 for Pragmatists
 
Dist::Zilla - Maximum Overkill for CPAN Distributions
Dist::Zilla - Maximum Overkill for CPAN DistributionsDist::Zilla - Maximum Overkill for CPAN Distributions
Dist::Zilla - Maximum Overkill for CPAN Distributions
 
Perl 5.12 for Everyday Use
Perl 5.12 for Everyday UsePerl 5.12 for Everyday Use
Perl 5.12 for Everyday Use
 
Dist::Zilla
Dist::ZillaDist::Zilla
Dist::Zilla
 
Antediluvian Unix: A Guide to Unix Fundamentals
Antediluvian Unix: A Guide to Unix FundamentalsAntediluvian Unix: A Guide to Unix Fundamentals
Antediluvian Unix: A Guide to Unix Fundamentals
 
Perl 5.10 for People Who Aren't Totally Insane
Perl 5.10 for People Who Aren't Totally InsanePerl 5.10 for People Who Aren't Totally Insane
Perl 5.10 for People Who Aren't Totally Insane
 
Writing Modular Command-line Apps with App::Cmd
Writing Modular Command-line Apps with App::CmdWriting Modular Command-line Apps with App::Cmd
Writing Modular Command-line Apps with App::Cmd
 
Crafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::ExporterCrafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::Exporter
 
How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!
How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!
How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!
 

Dernier

Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessPixlogix Infotech
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 

Dernier (20)

Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 

i &lt;3 email

  • 1. the 2009 PEP talk!!!
  • 4. PEP: Thoughts from Pobox YAPC::NA 2006
  • 6. How I Learned To Stop Worrying and Love Email YAPC::NA 2007
  • 8. Email hates the living! YAPC::NA 2008
  • 9. What’s the best way to deal with horrible code?
  • 10. Write more code! ...so I did! The last year has been really productive. Lots of obnoxious problems were sorted out. I’m really happy with what we got accomplished, and so finally I can with a straight face...
  • 11. rjbs <3 email the 2009 PEP talk!!!
  • 13. MIME::Lite Mail::Send Mail::Sender Mail::Sendmail so, here are some of the libraries for sending mail. these all let you specify subject, to/from, and content -- so you can’t actually make an email just hwo you want and pass it in. worthless for any real use
  • 14. Mail::Mailer this lets you send mail through pluggable backends, and you provide the mail message. not bad, but not great; it has this weird API where it isa IO::Handle and you print to it like a filehandle to send your message. subclassing is a pain because it’s a blessed globref
  • 15. Email::Send Email::Send simplifies by expecting a string, being a hashref, and being in theory easier to extend (by using Module::Pluggable) unfortunately, this pluggability (and some other oddities) ends up making extending things harder and can cause it to silently lose mail. for real.
  • 16. this is probably about about as good as a number of them.
  • 17. system(“sendmail @opts < $tempfile”) && die sprintf “sendmail died: %s”, errstr($?); this is probably about about as good as a number of them.
  • 18. Mail::Transport So, Mail::Transport isn’t bad. It’s part of the Mail-Box distro, which means it tends to get things right, but it also tends to be confusing and overwhelming for new users. If you’re already using it happily, that’s great! We weren’t, though, and so we wrote something new, built using just the ideas we liked from Email::Send, and
  • 19.
  • 24. Email::Sender Email-Sender uses Møøse Email::Sender is a role you use Email::Sender::Simple
  • 25. Email::Sender::Simple use Email::Sender::Simple qw(sendmail); my $email = $customer->build_welcome_email; sendmail($email); Yup. That’s about it. That will try to send mail with either sendmail or SMTP, depending on what’s available. If it can’t send the message, it will throw.
  • 26. Email::Sender::Simple use Email::Sender::Simple qw(sendmail); my $email = $customer->build_welcome_email; sendmail( $email, { to => @rcpts, from => $sender, } ); In other words, you can specify the envelope separately from the header. This is of *vital* importance to real email work. VERP, mailing lists, especially.
  • 27. Email::Sender::Simple my $smtp = Email::Sender::Transport::SMTP->new({ host => ‘sasl.pobox.com’, port => 26, }); sendmail($email, { transport => $smtp }); If you don’t like the auto-detected transport, you can specify one. Transports are really easy to write, and a bunch already exist:
  • 28. Transports SQLite is especially handy because you can dump all mail from a forking program into an easy-to-test database.
  • 29. Transports Sendmail SQLite is especially handy because you can dump all mail from a forking program into an easy-to-test database.
  • 30. Transports Sendmail SMTP SQLite is especially handy because you can dump all mail from a forking program into an easy-to-test database.
  • 31. Transports Sendmail SMTP Persist. SMTP SQLite is especially handy because you can dump all mail from a forking program into an easy-to-test database.
  • 32. Transports Sendmail SMTP Persist. SMTP Maildir, Mbox SQLite is especially handy because you can dump all mail from a forking program into an easy-to-test database.
  • 33. Transports Sendmail DevNull SMTP Persist. SMTP Maildir, Mbox SQLite is especially handy because you can dump all mail from a forking program into an easy-to-test database.
  • 34. Transports Sendmail DevNull SMTP Print Persist. SMTP Maildir, Mbox SQLite is especially handy because you can dump all mail from a forking program into an easy-to-test database.
  • 35. Transports Sendmail DevNull SMTP Print Persist. SMTP Test Maildir, Mbox SQLite is especially handy because you can dump all mail from a forking program into an easy-to-test database.
  • 36. Transports Sendmail DevNull SMTP Print Persist. SMTP Test Maildir, Mbox SQLite SQLite is especially handy because you can dump all mail from a forking program into an easy-to-test database.
  • 37. Email::Sender::Simple my $smtp = Email::Sender::Transport::SMTP->new({ host => ‘sasl.pobox.com’, port => 26, }); sendmail($email, { transport => $smtp }); so, you can do this, that’s fine, and you can use any of those cool transports when you call sendmail... but what about if you want to change the whole default?
  • 38. Email::Sender::Simple walrus!rjbs:~$ EMAIL_SENDER_TRANSPORT=Maildir my-awesome-program --auden now *every* call to Email::Sender::Simple->send will deliver to ./Maildir so you can see exactly what it would have sent
  • 39. Programmable Failure so, for example, we have a system that distributes mail across a cluster of hosts with various mechanisms to cope with failure Failable lets me test them by using a mailer that always works wrapped in predictable failure, easily
  • 40. Programmable Failure ::Failable transport so, for example, we have a system that distributes mail across a cluster of hosts with various mechanisms to cope with failure Failable lets me test them by using a mailer that always works wrapped in predictable failure, easily
  • 41. Programmable Failure ::Failable transport wrap any transport so, for example, we have a system that distributes mail across a cluster of hosts with various mechanisms to cope with failure Failable lets me test them by using a mailer that always works wrapped in predictable failure, easily
  • 42. Programmable Failure ::Failable transport wrap any transport make it fail when you want so, for example, we have a system that distributes mail across a cluster of hosts with various mechanisms to cope with failure Failable lets me test them by using a mailer that always works wrapped in predictable failure, easily
  • 44. Other Random Senderisms structured failure
  • 45. Other Random Senderisms structured failure partial successes
  • 49. these are pretty low level
  • 50. you probably want to send only a few messages (but with differences)
  • 51. MIME Crap to Deal With
  • 52. MIME Crap to Deal With header encoding
  • 53. MIME Crap to Deal With header encoding content encoding
  • 54. MIME Crap to Deal With header encoding content encoding building html & plain parts
  • 55. MIME Crap to Deal With header encoding content encoding building html & plain parts attaching files
  • 56. Other Crap to Deal With
  • 57. Other Crap to Deal With templated documents
  • 58. Other Crap to Deal With templated documents validate parameters
  • 59. Other Crap to Deal With templated documents validate parameters reusable hunks of content
  • 60.
  • 61. hate!
  • 66. Existing Solutions none? horrible hacks make a template in TT render to html
  • 67. Existing Solutions none? horrible hacks make a template in TT render to html html-to-text
  • 68. Existing Solutions none? horrible hacks make a template in TT render to html html-to-text hope you guess right at headers
  • 69.
  • 73. Email::MIME::Kit a bunch of files with instructions on how to assemble them
  • 74. Email::MIME::Kit a bunch of files with instructions on how to assemble them and some other data
  • 75. Kit Manifest { "renderer" : "TT", "header" : [ { "Subject": "Hello [% user.name %]" }, { "From": "Test Sender <test@test.com>" }, { "To": "[% user.email %]" } ], "alternatives": [ { "type": "text/plain", "path": "body.txt" }, { "type": "text/html", "path": "body.html" } ], "attachments": [ { "path": "demands.rtf" } ] }
  • 76. Assembling the Kit my $kit = Email::MIME::Kit->new({ source => ‘msg.mkit’ }); my $email = $kit->assemble({ user => $user_object }); sendmail($email);
  • 77. Dear , Thank you for being a customer since . Your account has been due to . Please contact before at or we will be forced to your lovely wife Tracy’s head. Cheers, Anonymous Ugh. Our $user_object was undef. Now we get crap that looks like mail but stinks and makes us look like idiots. We can plug in a validator pretty easily, though...
  • 78. Kit Manifest { "renderer" : "TT", “validator”: “Rx”, "header" : [ { "Subject": "Hello [% user.name %]" }, { "From": "Test Sender <test@test.com>" }, { "To": "[% user.email %]" } ], "alternatives": [ { "type": "text/plain", "path": "body.txt" }, { "type": "text/html", "path": "body.html" } ], "attachments": [ { "path": "demands.rtf" } ] }
  • 79. rx.json { “type”: “//rec”, “required”: { “user”: { “type”: “/perl/obj”, “isa” : “User::Account” } } }
  • 80. Assembling the Kit my $kit = Email::MIME::Kit->new({ source => ‘msg.mkit’ }); my $email = $kit->assemble({ user => undef }); undefined value tag: [ “/err/nil” ], data path: [ “user” ], schema path: [ “user” ] at slide 42, line 3
  • 82. Annoying Crap: Dealt With if user.name is Ævar...
  • 83. Annoying Crap: Dealt With if user.name is Ævar... if attachments are binary...
  • 84. Annoying Crap: Dealt With if user.name is Ævar... if attachments are binary... text-only (singlepart) mail...
  • 85. Annoying Crap: Dealt With if user.name is Ævar... if attachments are binary... text-only (singlepart) mail... HTML with images as attachments...
  • 86. ...so what’s still annoying?
  • 87. Some Kits... so, you love mkits and you’re writing them all the time... now you start having this problem...
  • 88. Some Kits... ./body.html ./body.txt ./logo.jpg ./background.jpg ./manifest.json so, you love mkits and you’re writing them all the time... now you start having this problem...
  • 89. Some Kits... ./body.html ./body.html ./body.txt ./body.txt ./logo.jpg ./logo.jpg ./background.jpg ./background.jpg ./manifest.json ./manifest.json so, you love mkits and you’re writing them all the time... now you start having this problem...
  • 90. Some Kits... ./body.html ./body.html ./body.txt ./body.txt ./logo.jpg ./logo.jpg ./background.jpg ./background.jpg ./manifest.json ./manifest.json ./body.html ./body.txt ./logo.jpg ./background.jpg ./manifest.json so, you love mkits and you’re writing them all the time... now you start having this problem...
  • 91. Some Kits... ./body.html ./body.html ./body.txt ./body.txt ./logo.jpg ./logo.jpg ./background.jpg ./background.jpg ./manifest.json ./manifest.json ./body.html ./body.html ./body.txt ./body.txt ./logo.jpg ./logo.jpg ./background.jpg ./background.jpg ./manifest.json ./manifest.json so, you love mkits and you’re writing them all the time... now you start having this problem...
  • 92. Some Kits... ./body.html ./body.html ./body.txt ./body.txt ./logo.jpg ./logo.jpg ./background.jpg ./background.jpg ./manifest.json ./manifest.json ./body.html ./body.html ./body.txt ./body.txt ./logo.jpg ./logo.jpg ./background.jpg ./background.jpg ./manifest.json ./manifest.json those files are identical everywhere. blaugh! duplication baaaaaaaaaad
  • 94. The Kit Reader EMKit gets at its contents with the kit reader
  • 95. The Kit Reader EMKit gets at its contents with the kit reader normally, just looks for files in the kit directory
  • 96. SWAK! /fs (can be chrooted) /dist /kit (default, too)
  • 97. SWAK! you can write your own kit reader /fs (can be chrooted) /dist /kit (default, too)
  • 98. SWAK! you can write your own kit reader SWAK: Path::Resolver /fs (can be chrooted) /dist /kit (default, too)
  • 99. SWAK! you can write your own kit reader SWAK: Path::Resolver /kit/body.html /fs (can be chrooted) /dist /kit (default, too)
  • 100. SWAK! you can write your own kit reader SWAK: Path::Resolver /kit/body.html body.html /fs (can be chrooted) /dist /kit (default, too)
  • 101. SWAK! you can write your own kit reader SWAK: Path::Resolver /kit/body.html body.html /fs/usr/share/app/body.html /fs (can be chrooted) /dist /kit (default, too)
  • 102. SWAK in Use ./body.html ./body.txt ./manifest.json ./body.html ./body.txt ./manifest.json ./body.html ./body.txt ./manifest.json So, we can take those common files and put them in our dist’s shared resources, and reference them with the “/dist/” prefix, which finds stuff in share-dirs. So, awesome! What’s still annoying?
  • 103. SWAK in Use ./body.html ./body.txt ./manifest.json ./body.html /dist/YourApp/logo.jpg /dist/YourApp/background.jpg ./body.txt ./manifest.json ./body.html ./body.txt ./manifest.json So, we can take those common files and put them in our dist’s shared resources, and reference them with the “/dist/” prefix, which finds stuff in share-dirs. So, awesome! What’s still annoying?
  • 104. SWAK in Use ./body.html ./body.txt ./manifest.json ./body.html /dist/YourApp/logo.jpg /dist/YourApp/background.jpg ./body.txt ./manifest.json ./body.html ./body.txt ./manifest.json almost certainly, the html and text parts are (a) really close to each other within one kit (b) contain really different parts between kits (c) contain common boilerplate between kits
  • 105. EMK::Assembler::Markdown ./body.mkdn ./manifest.json /dist/YourApp/logo.jpg /dist/YourApp/background.jpg ./body.mkdn ./manifest.json ./body.mkdn ./manifest.json So, let’s fix that, too. We replace the text and html parts with a single Markdown document. We’ll use the Markdown itself for the plaintext part and we’ll turn it into HTML to use in the HTML part. Of course, this still needs work. We want wrapper stuff and copyright and so on in both parts.
  • 106. EMK::Assembler::Markdown ./body.mkdn ./manifest.json /dist/YourApp/logo.jpg /dist/YourApp/background.jpg ./body.mkdn /dist/YourApp/wrapper.html ./manifest.json /dist/YourApp/wrapper.text ./body.mkdn ./manifest.json