frank1 has asked for the wisdom of the Perl Monks concerning the following question:

Regarding my question on Send email with recipient name, which has taken some time without response, i have came up with something like below, but its not working, even reporting any error.

#!/usr/bin/perl -wT use lib '.'; use strict; use warnings; use DBI; use Email::Sender::Simple qw(sendmail); use Email::Sender::Transport::SMTP (); use Email::Simple (); use Email::Simple::Creator (); use CGI qw/:standard/; use CGI::Carp qw(fatalsToBrowser warningsToBrowser); $CGI::DISABLE_UPLOADS = 1; $CGI::POST_MAX = 1048576; print "Content-type: text/html\n\n"; my $host = "host"; my $usr = "user"; my $pwd = "pwd"; my $dbname = "datname"; my $dbh = DBI->connect("DBI:mysql:$dbname:$host", $usr, $pwd, { RaiseError => 1, }) or die $DBI::errstr; my @names; my @rcpts; my $name; my $rcpt; my $Response; sub getusers { my $sth = $dbh->prepare("SELECT * FROM bmop"); $sth->execute(); while (my @row = $sth->fetchrow_array) { $name = $row[2]; # Get their names $rcpt = $row[5]; # Get their emails push @names,$name; push @rcpts,$rcpt; } } sub getready { my $j = 0; foreach my $i(@names){ ## Grab user info from the table $name = $names[$j]; # Get their name $rcpt = $rcpts[$j]; # Get their email sendmail(); $j++; } } sub sendmail { my $sub = "Test mail"; my $msg = "<p> Hi $name </p>"; my $smtpserver = 'smtp.xxxxxx.com'; my $smtpport = 587; my $smtpuser = 'dddddd'; my $smtppassword = 'ddddd'; my $transport = Email::Sender::Transport::SMTP->new({ host => $smtpserver, ssl => 'starttls', port => $smtpport, sasl_username => $smtpuser, sasl_password => $smtppassword, }); my $email = Email::Simple->create( header => [ To => $rcpt, From => 'xxx@xxxx.com', Subject => $sub, 'Content-Type' => 'text/html', ], body => $msg, ); sendmail($email, { transport => $transport }); $Response = "Process started"; }

Replies are listed 'Best First'.
Re: mail with users names
by hv (Prior) on Jan 01, 2024 at 17:29 UTC

    What have you done to try and debug it?

    My starting point would be to test it outside of the CGI environment: it is far easier to debug things that way.

    I note that you have a function called sendmail, and you also import a function called sendmail, and you call sendmail(...) inside your sendmail function. Your own defined function will override the imported one, so this will lock you into infinite recursion on your own function. In a command-line environment you'd see a warning from defining a function with the same name; I suspect that in your CGI environment it is trying to show you those warnings, but it's saving them up to send to the browser and due to the infinite loop never getting to the point it actually sends them.

    If your sendmail function took its inputs as arguments, and verified them, you might also have had a chance to spot something was wrong and bail out: that's a benefit of using better design.

      i tried to debug but i get no any error which has made me also get confused, even if i take the script to command line there is no error, after running the script

        You never call getready or sendmail. How do you think you kick off the mail sending?

        A reply falls below the community's threshold of quality. You may see it by logging in.
        there is no error

        Does the script exit?

        I suspect not.

        I haven't tried running your script but it looks to me like you have an infinite loop. So the script goes round and round merrily executing forever without error because it is doing what the code says it should. If the code runs but doesn't do what you want it to, that's not an error, it's a bug!

Re: mail with users names
by tybalt89 (Monsignor) on Jan 02, 2024 at 00:35 UTC

    The code consist of some setup and then three sub's which never get called. Well, sendmail gets called within getready, but no one calls getready...
    When I comment out the DBI code (since I don't have your database) and run the script, it prints out

    Content-type: text/html

    and exits, just as expected.

      thats the best i tried, coz i thought when i call sendmail. the sending process will start.

Re: mail with users names
by Bod (Parson) on Jan 01, 2024 at 22:58 UTC

    Not directly related to your mail sending issue but I'm including it because I always find it helpful when people make constructive criticism of my code...

    Your script makes use of CGI::Carp through

    use CGI::Carp qw(fatalsToBrowser warningsToBrowser);
    But it doesn't call the warningsToBrowser(); method. This method works differently to fatalsToBrowser. The latter displays the error as part of the HTTP 500 screen. However, for a warning, CGI::Carp can't display a message that early, in other words, before the browser gets the HTTP headers. So you have to choose when to send any warning after the HTTP headers by calling warningsToBrowser(1); (with any true value).

    The warning manifests as an HTML comment in the webpage at the point you call the warningsToBrowser(); method. It is usually best to do it at the end so the warning appears at the bottom of the HTML source code. This saves you having to hunt for it!

Re: mail with users names
by LanX (Saint) on Jan 01, 2024 at 16:51 UTC
    > 'https://perlmonks.org/?node_id=11155744'

    It might help to link to the old discussion:

    [id://11155744] -> Send email with recipient name

    From How to link which is always listed in the help section below the post form:

      Linking to a specific node by node_id:

      Now you can link to a specific node_id by using [id://979] which will make a link like vroom. You can also follow it up with link text that you want to use in place of the node title like so [id://131|The Default Page] whic creates a link like so: The Default Page

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    see Wikisyntax for the Monastery

Re: mail with users names
by choroba (Cardinal) on Jan 04, 2024 at 14:40 UTC
    Crossposted to StackOverflow.

    Crossposting is allowed, but it's considered polite to announce it to prevent people not visiting both sites from hacking on a problem already solved at the other end of the internet.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

      i have fixed my script and working very well now. without any help from anyone. i just went through each sub function to make sure each works

      wat was confusing me is that. i thought i can just call only 1 function and leave others behind and run themselves on script execution

      Now my mine point is to work on this script efficacy and effective to deliver msg to over 100k receivers

      Anyone want to addone something, so it become more effective on delivering msg to 100k, i appreciate

      #!/usr/bin/perl -wT use lib '.'; use warnings; use DBI; use Email::Sender::Simple qw(sendmail); use Email::Sender::Transport::SMTP (); use Email::Simple (); use Email::Simple::Creator (); use CGI qw/:standard/; use CGI::Carp qw(fatalsToBrowser warningsToBrowser); $CGI::DISABLE_UPLOADS = 1; $CGI::POST_MAX = 1048576; print "Content-type: text/html\n\n"; my $host = "xxxxx"; my $usr = "xxxxx"; my $pwd = "xxxxx"; my $dbname = "xxxxx"; my $dbh = DBI->connect("DBI:mysql:$dbname:$host", $usr, $pwd, { RaiseError => 1, }) or die $DBI::errstr; sub getusers { my $sth = $dbh->prepare("SELECT * FROM bmop"); $sth->execute(); while (my @row = $sth->fetchrow_array) { $name = $row[2]; # Get their names $rcpt = $row[5]; # Get their emails push @names,$name; push @rcpts,$rcpt; } } getusers(); sub getready { my $j = 0; foreach my $i(@names){ ## Grab user info from the table $rcv_names = $names[$j]; # Get their name $rcv_emails = $rcpts[$j]; # Get their email mail(); $j++; } } getready(); sub mail { my $sub = "Test mail"; my $msg = "<p> Hi $rcv_names </p>"; my $smtpserver = 'xxxx'; my $smtpport = 587; my $smtpuser = 'xxxxx'; my $smtppassword = 'x+x+x+'; my $transport = Email::Sender::Transport::SMTP->new({ host => $smtpserver, ssl => 'starttls', port => $smtpport, sasl_username => $smtpuser, sasl_password => $smtppassword, }); my $email = Email::Simple->create( header => [ To => $rcv_emails, From => 'xxxxx@xxxxx.com', Subject => $sub, 'Content-Type' => 'text/html', ], body => $msg, ); sendmail($email, { transport => $transport }); }