Problem with email attachment, 1 becomes 10

Discussion in 'Perl Misc' started by M.O.B. i L., May 5, 2008.

  1. M.O.B. i L.

    M.O.B. i L. Guest

    I'm trying to write a program that can send out mails to companies where
    I'm interested in working. These mails are the same except that the
    company name is switched. My CV should be attached as a pdf-file.
    The problem is that I don't get one attachment, but ten! Also the
    message is repeated 10 times. If I change the program by uncommenting
    the commented line in the function load() it works but then it doesn't
    send the correct pdf-file. The CV is 129490 bytes. How could I change
    this program so that there is only one attachment and no repeated messages?

    In the program below some long lines might have been splitted.

    #!/usr/bin/perl

    # jobapplier.pl vN/A (Buggy!)
    # Author: Mikael O. Bonnier, ,
    http://www.df.lth.se/~mikaelb/
    # Copyright (C) 2008 by Mikael O. Bonnier, Lund, Sweden.
    # License: GNU GPL v3 or later, http://www.gnu.org/licenses/gpl-3.0.txt

    use strict;
    use Email::Send;
    use Email::Simple::Creator;
    use Email::MIME::Modifier;
    use DBI;
    use MIME::Words qw/encode_mimewords/;
    use File::stat;

    my %settings = (
    SMTP => 'mail.df.lth.se',
    PORT => 588,
    FROM_DOMAIN => 'cust.bredbandsbolaget.se',
    DB => 'jobapplier_test',
    DB_HOST => 'localhost',
    FROM => '',
    SUBJECT => 'Intresseanmälan som fysiker eller programutvecklare',
    BODY =>
    'Det skulle vara intressant att jobba hos er på $cCompany.',
    UPLDDIR => '../Documents/LyX',
    FILE => 'MOB_CV.pdf',
    );
    @ARGV == 4
    or die
    'Provide username and password for the SMTP and the MySQL server,
    respectively,'
    . " on the command line.\n";
    @settings{qw( USER PASS DB_USER DB_PASS)} = @ARGV;

    my $dbh = DBI->connect( "DBI:mysql:$settings{DB}:$settings{DB_HOST}",
    $settings{DB_USER}, $settings{DB_PASS} );

    my $q = q|select cCompany, cEmail
    from Contacts
    order by cId asc|;
    my $sth = $dbh->prepare($q);
    $sth->execute;
    my $as = [];
    while ( my $hr = $sth->fetchrow_hashref ) {
    push @{$as}, $hr;
    }
    $dbh->disconnect;

    my $mailer = Email::Send->new(
    {
    mailer => 'SMTP::TLS',
    mailer_args => [
    Host => $settings{SMTP},
    Port => $settings{PORT},
    User => $settings{USER},
    Password => $settings{PASS},
    Hello => $settings{FROM_DOMAIN},
    ]
    }
    );

    for my $row (@$as) {
    my $body_text = $settings{BODY};
    $body_text =~ s/\$cCompany/$row->{cCompany}/g;
    my $email = Email::Simple->create(
    header => [
    From => $settings{FROM},
    To => $row->{cEmail},
    Subject => encode_mimewords( $settings{SUBJECT} ),
    'Content-Type' => 'text/plain; charset="utf-8"',
    ],
    body => $body_text,
    );
    my $body = load( $settings{UPLDDIR}, $settings{FILE} );
    my $part = Email::MIME->new('');
    $part->body_set($body);
    $part->disposition_set('attachment');
    $part->name_set( $settings{FILE} ); # Both needed?
    $part->filename_set( $settings{FILE} ); # Both needed?
    $part->encoding_set('base64');
    $part->content_type_set('application/octet-stream');
    my @more_parts = ($part);
    $email = Email::MIME->new( $email->as_string );
    $email->parts_add( \@more_parts );

    eval { $mailer->send($email) };
    die "Error sending email: $@" if $@;
    }

    sub load {
    my ( $upldDir, $inFile ) = @_;
    my $DNLDFILE;
    open $DNLDFILE, '<', "$upldDir/$inFile";
    binmode $DNLDFILE;
    my $st = stat $DNLDFILE;
    my $content;
    read $DNLDFILE, $content, $st->size;
    close $DNLDFILE;

    # $content = 'ABC';
    return $content;
    }

    __END__
     
    M.O.B. i L., May 5, 2008
    #1
    1. Advertising

  2. M.O.B. i L.

    Ben Bullock Guest

    On Mon, 05 May 2008 03:07:53 +0200, M.O.B. i L. wrote:

    > I'm trying to write a program that can send out mails to companies where
    > I'm interested in working. These mails are the same except that the
    > company name is switched. My CV should be attached as a pdf-file. The
    > problem is that I don't get one attachment, but ten! Also the message is
    > repeated 10 times. If I change the program by uncommenting the commented
    > line in the function load() it works but then it doesn't send the
    > correct pdf-file. The CV is 129490 bytes. How could I change this
    > program so that there is only one attachment and no repeated messages?


    I don't know the answer to your question, but after reading it I wonder
    if anyone else can solve it for you, so I'll post my advice instead. One
    piece of advice which has been useful to me which I learnt from the
    posting guidelines for this group is, before posting, to always try to
    reduce the problem to the minimum possible, let's say ten or twenty lines
    of code:

    "First make a short (less than 20-30 lines) and *complete* program
    that illustrates the problem you are having. People should be able
    to run your program by copy/pasting the code from your article. (You
    will find that doing this step very often reveals your problem
    directly. Leading to an answer much more quickly and reliably than
    posting to Usenet.)"

    In the case of your program there are two big chunks: first, lots of
    stuff involving reading lines from the database, which is where I suspect
    the problem has occurred, probably some kind of slip-up, but I can't
    prove this because I don't have the database available, and then there is
    an almost separate piece of code which involves sending a mail with an
    attachment, which might be where the bug happened, although I think it's
    unlikely.

    If I was going to seriously try to solve your problem, I would first of
    all split the program into two pieces, one which gets those database
    lines and just prints them to STDOUT, and another piece which sends just
    one mail with some fixed parameters, written into the file itself rather
    than pulled from a database, and see which one of these two pieces is
    going wrong.

    Then, if I still couldn't debug it myself, I might try posting whichever
    of the two pieces the problem had occurred in to the newsgroup. But it's
    very hard (for me at least) to work out what might have happened in your
    program because of all the dependencies. As it says in the quote above,
    if you can reduce the dependencies to a minimum piece of code which
    anybody can run, you'll probably end up solving your own problem into the
    bargain. I have repeatedly had problems in Perl which I thought were
    incredibly difficult, ended up frustrated enough to want to post them
    here, and in the business of reducing them into a short newsgroup post as
    described, I ended up surprising myself by working out what the bug was
    without having to post it.

    Having said all that, perhaps someone will spot the bug in your code the
    next minute after I post this, so who knows?
     
    Ben Bullock, May 5, 2008
    #2
    1. Advertising

  3. M.O.B. i L.

    Bill H Guest

    On May 4, 9:07 pm, "M.O.B. i L." <> wrote:
    > for my $row (@$as) {
    >      my $body_text = $settings{BODY};
    >      $body_text =~ s/\$cCompany/$row->{cCompany}/g;
    >      my $email = Email::Simple->create(
    >          header => [
    >              From           => $settings{FROM},
    >              To             => $row->{cEmail},
    >              Subject        => encode_mimewords( $settings{SUBJECT} ),
    >              'Content-Type' => 'text/plain; charset="utf-8"',
    >          ],
    >          body => $body_text,
    >      );
    >      my $body = load( $settings{UPLDDIR}, $settings{FILE} );
    >      my $part = Email::MIME->new('');
    >      $part->body_set($body);
    >      $part->disposition_set('attachment');
    >      $part->name_set( $settings{FILE} );        # Both needed?
    >      $part->filename_set( $settings{FILE} );    # Both needed?
    >      $part->encoding_set('base64');
    >      $part->content_type_set('application/octet-stream');
    >      my @more_parts = ($part);
    >      $email = Email::MIME->new( $email->as_string );
    >      $email->parts_add( \@more_parts );
    >
    >      eval { $mailer->send($email) };
    >      die "Error sending email: $@" if $@;


    I think your issue has to do with the "more_parts".

    Bill H
     
    Bill H, May 7, 2008
    #3
  4. M.O.B. i L.

    M.O.B. i L. Guest

    Ben Bullock wrote:
    > On Mon, 05 May 2008 03:07:53 +0200, M.O.B. i L. wrote:
    >
    >> I'm trying to write a program that can send out mails to companies where
    >> I'm interested in working. These mails are the same except that the
    >> company name is switched. My CV should be attached as a pdf-file. The
    >> problem is that I don't get one attachment, but ten! Also the message is
    >> repeated 10 times. If I change the program by uncommenting the commented
    >> line in the function load() it works but then it doesn't send the
    >> correct pdf-file. The CV is 129490 bytes. How could I change this
    >> program so that there is only one attachment and no repeated messages?

    >
    > I don't know the answer to your question, but after reading it I wonder
    > if anyone else can solve it for you, so I'll post my advice instead. One
    > piece of advice which has been useful to me which I learnt from the
    > posting guidelines for this group is, before posting, to always try to
    > reduce the problem to the minimum possible, let's say ten or twenty lines
    > of code:
    >
    > "First make a short (less than 20-30 lines) and *complete* program
    > that illustrates the problem you are having. People should be able
    > to run your program by copy/pasting the code from your article. (You
    > will find that doing this step very often reveals your problem
    > directly. Leading to an answer much more quickly and reliably than
    > posting to Usenet.)"
    >
    > In the case of your program there are two big chunks: first, lots of
    > stuff involving reading lines from the database, which is where I suspect
    > the problem has occurred, probably some kind of slip-up, but I can't
    > prove this because I don't have the database available, and then there is
    > an almost separate piece of code which involves sending a mail with an
    > attachment, which might be where the bug happened, although I think it's
    > unlikely.
    >
    > If I was going to seriously try to solve your problem, I would first of
    > all split the program into two pieces, one which gets those database
    > lines and just prints them to STDOUT, and another piece which sends just
    > one mail with some fixed parameters, written into the file itself rather
    > than pulled from a database, and see which one of these two pieces is
    > going wrong.
    >
    > Then, if I still couldn't debug it myself, I might try posting whichever
    > of the two pieces the problem had occurred in to the newsgroup. But it's
    > very hard (for me at least) to work out what might have happened in your
    > program because of all the dependencies. As it says in the quote above,
    > if you can reduce the dependencies to a minimum piece of code which
    > anybody can run, you'll probably end up solving your own problem into the
    > bargain. I have repeatedly had problems in Perl which I thought were
    > incredibly difficult, ended up frustrated enough to want to post them
    > here, and in the business of reducing them into a short newsgroup post as
    > described, I ended up surprising myself by working out what the bug was
    > without having to post it.
    >
    > Having said all that, perhaps someone will spot the bug in your code the
    > next minute after I post this, so who knows?


    You're right but if I had been lucky and someone had had this problem
    before I could have saved a day. I did follow your advice on isolating
    the problem.

    I found a fix, see
    <http://rt.cpan.org/Public/Bug/Display.html?id=33031>. There is a bug in
    sub datasend in /usr/local/share/perl/5.8.8/Net/SMTP/TLS.pm.

    Now I learned one should always read the bug reports carefully.

    With the fix this shortened script works (long lines may have wrapped):
    #!/usr/bin/perl

    # appliertest.pl v0.0.0
    # Author: Mikael O. Bonnier, ,
    http://www.df.lth.se/~mikaelb/
    # Copyright (C) 2008 by Mikael O. Bonnier, Lund, Sweden.
    # License: GNU GPL v3 or later, http://www.gnu.org/licenses/gpl-3.0.txt

    use strict;
    use Email::Send;
    use Email::MIME::Creator;
    use MIME::Words qw/encode_mimewords/;
    use IO::All;

    my %settings = (
    SMTP => 'smtp.gmail.com',
    PORT => 587,
    FROM_DOMAIN => '',
    FROM => '',
    SUBJECT => 'Intresseanmälan som fysiker eller programutvecklare',
    BODY =>
    'Det skulle vara intressant att jobba hos er på $cCompany.',
    UPLDDIR => '../Documents/LyX',
    FILE => 'MOB_CV.pdf',
    );
    @ARGV == 4
    or die
    'Provide username and password for the SMTP server, and company name and
    email'
    . " on the command line.\n";
    @settings{qw( USER PASS CCOMPANY CEMAIL)} = @ARGV;

    my $mailer = Email::Send->new(
    {
    mailer => 'SMTP::TLS',
    mailer_args => [
    Host => $settings{SMTP},
    Port => $settings{PORT},
    User => $settings{USER},
    Password => $settings{PASS},
    Hello => $settings{FROM_DOMAIN},
    ]
    }
    );

    my $row =
    {
    cCompany => $settings{CCOMPANY},
    cEmail => $settings{CEMAIL},
    };

    {
    my $body_text = $settings{BODY};
    $body_text =~ s/\$cCompany/$row->{cCompany}/g;

    # multipart message
    my @parts = (
    Email::MIME->create(
    attributes => {
    content_type => 'text/plain',
    encoding => '8bit',
    charset => 'utf-8',
    },
    body => $body_text,
    ),
    Email::MIME->create(
    attributes => {
    filename => $settings{FILE},
    content_type => 'application/pdf',
    encoding => 'base64',
    disposition => 'inline',
    name => $settings{FILE},
    },
    body => io( $settings{UPLDDIR}.'/'.$settings{FILE} )->all,
    ),
    );

    my $email = Email::MIME->create(
    header => [
    From => $settings{FROM},
    'Reply-To' => $settings{FROM},
    To => $row->{cEmail},
    'User-Agent' => 'Thunderbird 2.0.0.14 (X11/20080505)',
    # 'MIME-Version' => '1.0',
    Subject => encode_mimewords( $settings{SUBJECT} ),
    ],
    attributes => {
    charset => '',
    },
    parts => [ @parts ],
    );

    eval { $mailer->send($email) };
    die "Error sending email: $@" if $@;
    }

    __END__
     
    M.O.B. i L., May 8, 2008
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    9
    Views:
    1,009
    Juha Nieminen
    Aug 22, 2007
  2. Alan Harris-Reid

    Email attachment problem

    Alan Harris-Reid, Apr 29, 2010, in forum: Python
    Replies:
    0
    Views:
    274
    Alan Harris-Reid
    Apr 29, 2010
  3. Alan Harris-Reid

    Binary file email attachment problem

    Alan Harris-Reid, May 10, 2010, in forum: Python
    Replies:
    0
    Views:
    401
    Alan Harris-Reid
    May 10, 2010
  4. Stef Mientki

    and becomes or and or becomes and

    Stef Mientki, May 22, 2011, in forum: Python
    Replies:
    9
    Views:
    323
    Chris Angelico
    May 28, 2011
  5. ecureuil
    Replies:
    0
    Views:
    337
    ecureuil
    May 28, 2006
Loading...

Share This Page