I am currently using Cpanel to setup an email forward that goes through a feature in CPanel email forwarding "Pipe to Program". In this perl script, I grab the headers and replace them with the Epson email print address, as Epson printers do not like direct forwarding. However, I am having the issue where sending to multiple users at once causes errors and it does not like more than 1 recipient.
My code is below:
#!/usr/bin/perl
use strict;
# Real email address for the printer
my $email = 'example#domain.com';
my $sm;
open($sm, "|/usr/sbin/sendmail -t");
my $in_header = 1;
while (my $line = <STDIN>) {
chomp $line;
# Empty line while in headers means end of headers
if ($in_header && $line eq '') {
$in_header = 0;
}
# Replace To: field if we're in headers
if ($in_header && $line =~ m/^To: /) {
$line = "To: $email";
}
# Pass through to sendmail
print $sm "$line\n";
}
close($sm);
I have a feeling the root of my issues comes from this line in my code:
# Replace To: field if we're in headers
if ($in_header && $line =~ m/^To: /) {
$line = "To: $email";
}
I have to admit something, I found this code snippet online and I am completely unfamiliar with Perl in order to find a viable solution to be able to forward to multiple emails without issue. Any indication on where I could start, even if a full solution isn't clear, would be very helpful.
Resources:
https://www.cravingtech.com/how-to-setup-epson-email-print-using-your-own-domain-name.html
#!/usr/bin/perl
use strict;
my $email = 'example#domain.com';
my $sm;
open($sm, "|/usr/sbin/sendmail -t");
my $in_header = 1;
my $in_to = 0;
while (my $line = <STDIN>) {
chomp $line;
# Empty line while in headers means end of headers
if ($in_header && $line eq '') {
$in_header = 0;
}
# Email Header
if ($in_header){
if($line =~ m/^To: /) {
$in_to = 1;
$line = "To: $email";
} elsif($in_to) {
if($line =~ /:/){
$in_to = 0;
}else{
next;
}
}
}
print $sm "$line\n";
}
close($sm);
This ended up being my solution after many hours of trial and error.
Just posting this here in case anyone runs into my very niche issue lol.
Thanks.
Related
I want to search my string Input at consol i.e. "VoLTE SIPTX: [SIPTX-SIP] ==> REGISTER" from the no of files In a directory (Sample data of the file Is shown below) but unable to do the same in the below code.
Here is my code:
use strict;
use warnings;
print "Entering the value i.e. the IMS Message to compare with";
my $value = '';
my $choice = '';
my $loop = '';
my $IMS_Message = '';
my $search = '';
my $kw = '';
print "\nThe script path & name is $0\n";
print "\nPlease enter desired number to select any of the following
(1) Start Comparing REGISTER message !!
(2) Start Comparing SUBSCRIBE message
(3) Start Comparing INVITE message \n";
$value = <STDIN>;
if ( $value == 1 ) {
print "\n Start Comparing REGISTER message\n\n";
$IMS_Message = "VoLTE SIPTX: [SIPTX-SIP] ==> REGISTER";
}
elsif ( $value == 2 ) {
print "\n SUBSCRIBE message Flow\n\n";
}
elsif ( $value == 3 ) {
print "\n INVITE message Flow\n\n";
}
else {
print "\nThe input is not valid!\n";
print "\nDo you want to continue selecting a Automation Mode again (Y or N)?\n";
$choice = <STDIN>;
if ( $choice eq /[Yy]/ ) {
test_loop();
}
else {
exit;
}
$kw = $IMS_Message;
#$search = qr/\Q$kw/;
$search = quotemeta( $kw );
for my $file ( grep {-f} glob '*main_log' ) {
open my $fh, '<', $file or die qq{Unable to open "$file" for input: $!};
while ( <$fh> ) {
if ( /$search/ ) {
printf "Found keyword %s in file %s, line %d: %s\n", $kw, $file, $., $_;
last;
}
}
}
}
Here is data of my files from which I want to search my string
**TempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTemp
*TempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTemp
VoLTE SIPTX: [SIPTX-SIP] ==> REGISTERTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTemp
tempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTemp
temptempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTemp
***tempTeTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTemp
the below code with command line does not work
use strict;
use warnings;
my $value = '';
my $choice = '';
my $loop = '';
my $IMS_Message = '';
print "\nThe script path & name is $0\n";
print "\nPlease enter desired number to select any of the following
(1) Start Comparing REGISTER message !! !!
(2) Start Comparing SUBSCRIBE message
(3) Start Comparing INVITE message \n";;
$value = <STDIN>;
if ($value == 1 )
{
print "\n Start Comparing REGISTER message\n\n";
my $IMS_Message = 'VoLTE SIPTX: [SIPTX-SIP] ==> REGISTER';
&IMS_Message_Check;
}
elsif ($value == 2)
{
print "\n SUBSCRIBE message Flow\n\n";
}
elsif ($value == 3)
{
print "\n INVITE message Flow\n\n";
}
else
{
print "\nThe input is not valid!\n";
print "\nDo you want to continue selecting a Automation Mode again (Y or N)?\n";
$choice = <STDIN>;
if( $choice =~ /[Yy]/) {
test_loop();
} else {
exit;
}
}
sub IMS_Message_Check{
print "\n";
print "Start Comparing REGISTER message\n\n";
#my $IMS_Message = 'VoLTE SIPTX: [SIPTX-SIP] ==> REGISTER';
my $kw = $IMS_Message;
my $search = qr/\Q$kw/;
for my $file ( grep { -f } glob '*main_log' ) {
open my $fh, '<', $file or die qq{Unable to open "$file" for input: $!};
while ( <$fh> ) {
if ( /$search/ ) {
printf "Found keyword %s in file %s, line %d: %s\n", $kw, $file, $., $_;
#last;
}
}
}
}
Okay, there are two main problems with your code
You have added my solution into the The input is not valid branch of your consecutive if statement. That is why I asked you to keep your code tidy and indented properly. You would have spotted it yourself if your indentation was at all organised
Your program is searching for VoLTE SIPTX: [SIPTX-SIP] ==> REGISTER while the text in the file is VoLTE SIPTX: [SIPTX-SIP] ==> REGISTER (your program has two spaces before REGISTER while your data has just one). Isn't that an obvious thing to check for?
I feel certain that you could have discovered these things for yourself, and you could certainly have read How to create a Minimal, Complete, and Verifiable example instead of posting very poor code and no sample data in the first place
I've ignored your command-line menu (which shouldn't be in the code at this stage anyway) including your call to the non-existent test_loop, and have written this, which performs properly. The bulk of it is a copy of the solution I provided to your previous question, which you said wasn't working
use strict;
use warnings;
print "\n";
print "Start Comparing REGISTER message\n\n";
my $IMS_Message = 'VoLTE SIPTX: [SIPTX-SIP] ==> REGISTER';
my $kw = $IMS_Message;
my $search = qr/\Q$kw/;
for my $file ( grep { -f } glob '*main_log' ) {
open my $fh, '<', $file or die qq{Unable to open "$file" for input: $!};
while ( <$fh> ) {
if ( /$search/ ) {
printf "Found keyword %s in file %s, line %d: %s\n", $kw, $file, $., $_;
last;
}
}
}
output
Start Comparing REGISTER message
Found keyword VoLTE SIPTX: [SIPTX-SIP] ==> REGISTER in file xmain_log, line 3: VoLTE SIPTX: [SIPTX-SIP] ==> REGISTERTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTempTemp
In my below program, I was trying to search a string from no of files In a folder but output Is printing in continuous manner rather than stopping after required search. Can some one pls help to point out the error ?
i.e. I am trying to Search the string "VoLTE SIPTX: [SIPTX-SIP] ==> REGISTER" from #files but I am not getting the desired output but I am getting repetitive output of my strings.
# #!/usr/bin/perl
# use strict;
use warnings;
&IMS_Compare_Message();
sub IMS_Compare_Message
{
print "Entering the value i.e. the IMS Message to compare with";
my $value = '';
my $choice = '';
my $loop = '';
print "\nThe script path & name is $0\n";
print "\nPlease enter desired number to select any of the following
(1) Start Comparing REGISTER message !!
(2) Start Comparing SUBSCRIBE message
(3) Start Comparing INVITE message \n";
$value = <STDIN>;
if ($value == 1 )
{
print "\n Start Comparing REGISTER message\n\n";
$IMS_Message = "VoLTE SIPTX: [SIPTX-SIP] ==> REGISTER";
#chomp ($IMS_Message);
}
elsif ($value == 2)
{
print "\n SUBSCRIBE message Flow\n\n";
}
elsif ($value == 3)
{
print "\n INVITE message Flow\n\n";
}
else
{
print "\nThe input is not valid!\n";
print "\nDo you want to continue selecting a Automation Mode again (Y or N)?\n";
$choice = <STDIN>;
if( $choice =~ /[Yy]/) {
test_loop();
} else {
exit;
}
}
my $kw = "$IMS_Message";
my #files = grep {-f} (<*main_log>);
foreach my $file (#files)
{
open(my $fh, '<', $file) or die $!;
my #content = <$fh>;
close($fh);
my $l = 0;
$search = chomp ($kw);
#my $search = quotemeta($kw);
foreach (#content)
{ # go through every line for this keyword
$l++;
if (/$search/)
{
printf 'Found keyword %s in file %s, line %d:%s'.$/, $kw, $file, $l, $_
}
}
}
}
After Modificaiton
# #!/usr/bin/perl
use strict;
use warnings;
print "Entering the value i.e. the IMS Message to compare with";
my $value = '';
my $choice = '';
my $loop = '';
my $IMS_Message = '';
my $search = '';
my $kw = '';
print "\nThe script path & name is $0\n";
print "\nPlease enter desired number to select any of the following
(1) Start Comparing REGISTER message !!
(2) Start Comparing SUBSCRIBE message
(3) Start Comparing INVITE message \n";
$value = <STDIN>;
if ($value == 1 )
{
print "\n Start Comparing REGISTER message\n\n";
$IMS_Message = "VoLTE SIPTX: [SIPTX-SIP] ==> REGISTER";
#chomp ($IMS_Message);
}
elsif ($value == 2)
{
print "\n SUBSCRIBE message Flow\n\n";
}
elsif ($value == 3)
{
print "\n INVITE message Flow\n\n";
}
else
{
print "\nThe input is not valid!\n";
print "\nDo you want to continue selecting a Automation Mode again (Y or N)?\n";
$choice = <STDIN>;
if( $choice eq /[Yy]/) {
test_loop();
} else {
exit;
}
$kw = $IMS_Message;
$search = qr/\Q$kw/;
for my $file ( grep { -f } glob '*main_log' ) {
open my $fh, '<', $file or die qq{Unable to open "$file" for input: $!};
while ( <$fh> ) {
if ( /$search/ ) {
printf "Found keyword %s in file %s, line %d: %s\n", $kw, $file, $., $_;
last;
}
}
}
}
Here are some observations on your code
Your approach to debugging appears to be to try things at random to see if they work. It would be far more fruitful to add diagnostic print statements so that you can compare variables' actual values with what you expect
Error and warning messages are useful information, and it is foolish to comment out use strict to make them go away
Don't call subroutines with an ampersand &. That hasn't been best practice for twenty years now
Lay your code out tidily and cinsistently, so that both you and any people you ask for help can read it easily. As it stands it is impossible to tell where blocks start and end without counting brace characters {...}
Variables should be declared with my as close as possible to their first point of use, and not all at once at the top of the file or subroutine
chomp is necessary only for strings that have been read from the terminal or from a file. It returns the number of characters removed, not the trimmed string
if( $choice =~ /[Yy]/ ) { ... } will check only whether the string contains a Y, so if the operator enters MARRY ME! it will return true. You should use string equality eq to check whether a single Y character has been typed
You shouldn't put scalar variables alone inside double quotes. At best it will make no difference, and just add noise to your code; at worst it will completely change the value of the variable. Just my $kw = $IMS_Message is correct
Unless you require non-sequential access to the contents of a file, it is best to use a while loop to read and process it line by line, rather than read the whole thing into an array and process each element of the array. This also allows you to use the built-in line number variable $. instead of implementing your own $l
The main problem is that you have derived $search from the result of chomp $kw, which sets $search to the number of characters removed by chomp. This is always zero because $kw is a copy of $IMS_Message, which has no newline at the end. That means you are checking all the lines of every file for the character 0, and not for the message that you intended. The correct way is my $search = quotemeta($kw) which you had in place but have commented out, presumably as a result of your policy of "debugging by guesswork"
Fixing these things, your code should look something like this
my $search = qr/\Q$kw/;
for my $file ( grep { -f } glob '*main_log' ) {
open my $fh, '<', $file or die qq{Unable to open "$file" for input: $!};
while ( <$fh> ) {
if ( /$search/ ) {
printf "Found keyword %s in file %s, line %d: %s\n", $kw, $file, $., $_;
last;
}
}
}
Can someone shed some light on how to have my script kick off only if new entries are found for the current hour? Our logs are based in 00 01 02, etc.
When this runs it will look for any accounts specified within my for loop and send an email if this particular user made a cert change for the hour. If a match is found then everything is fine.
But I am interested only in new real-time entries which I can't figure out.
This will be run from a cron, and I can't have it repeating the same entry. I am new to Perl and can't seem to figure this out.
I have tried the File::Tail module and other CPAN mods but due to company policies some mods are not allowed.
#!/usr/bin/perl -w
use strict;
my $flag = 0;
my $few = shift || 1;
my $id;
my $newline;
my $partyId;
my $userid;
my $tid;
my $infile;
my #Takeraccounts = ( 'SCN', 'CX' );
my $mail_dest = 'xxxxx#cx.com';
my %TIME;
(
$TIME{SEC}, $TIME{MIN}, $TIME{HOUR}, $TIME{MDAY}, $TIME{MON},
$TIME{YEAR}, $TIME{WDAY}, $TIME{YDAY}, $TIME{ISDST}
) = localtime(time);
my $OLD_MIN = $TIME{MIN};
my $OLD_HOUR = $TIME{HOUR};
my $cmd = "cat /raid/logs/`date +%H`";
my $out_file = "/home/resource/certchange.txt";
open FF, "$cmd |";
open( OUT, ">> $out_file" ) || die "Cannot open $out_file"; # temp file to which to write the formated output
while ( <FF> ) {
my $line = $_;
#chomp ($now_time);
$line =~ s/\n/ /;
if ( /Updating cert/ .. /,permissions/ ) {
$newline = "$line";
if ( $line =~ /Updating cert.*updated by (\w+)/ ) {
$id = $1;
}
if ( $newline =~ /UPDATE.*id:(\w+).*partyId:(\w+),perm:/ ) {
$userid = $1;
$partyId = $2;
foreach (#Takeraccounts) {
if ( $partyId =~ /$_/ ) {
print OUT "Certificate cert Updated by $id for userid $userid, PartyID $partyId\n";
open ML, "| mutt -e\"set realname='Support'; set use_from=yes; set from='support\#cx.com'; set envelope_from=yes\" -s ' Alert! cert CHANGED' -i $out_file -- $mail_dest";
close ML;
}
}
}
}
}
close FF;
close(OUT);
unlink $out_file;
I have a certain script , which will segregate the log file and put the result.txt which is comming as expected. But i want to sent mail after this segregate log file attach it in the text file and sent. There is no error in this script but i need to enhance it. Please help me on how i can use it
#use Win32;
if (#ARGV != 2) {
print "Please pass atleast one paramer\n";
print "Usage:\n\t $0 <file_name><Pattern>\n";
exit;
}
$File_name = $ARGV[0];
$res_File_name = $File_name . "\.result\.txt";
$Pattern = $ARGV[1];
chomp($Pattern);
open(FD,"$File_name") or die ("File '$File_name' could not be open \n");
open(WFD,">$res_File_name") or die("File $res_File_name could not be opened\n");
print "Enter begin match pattern: ";
$bgn = <stdin>;
chomp($bgn);
print $bgn;
print "Enter end match pattern: ";
$en = <stdin>;
chomp($en);
while ($line = <FD>) {
chomp($line);
if ($line =~ /^$bgn/) { #seaching a patter at begining of the string.
print WFD "Begin pattern '$bgn' matched with the line '$line'\n";
}
if ($line =~ /$en$/) { #seaching a patter at end of the string.
print WFD "End pattern '$en' matched with the line '$line'\n";
#exit;
}
print WFD $_ if(/$Pattern/);
# main();
# use constant Service_Name =>'MyServ'
# use constant Service_Desc =>'MyServDesc'
# sub main()
# {
# $opt=shift(# ARGV)||""
# if ($opt =~ /^(-i|--install)$/i)
# {
install _service( Service_Name, Service_Desc)
# }
# elsif ($opt =~ /^(-r|--remove)$/i)
# {
# remove_service(Service_Name);
# }
# elsif ($opt =~ /^(run)$/i)
#}
# here we create a log file wth STDOUT and STDERR
# The log file will be created with extension .log
$log = $cwd . $bn . ".log";
# open(STDOUT, ">> $log") or die "Couldn't open $log for appending: $!\n";
# open(STDERR, ">&STDOUT") or die "Could";
close(FD);
close(WFD);
The standard way to create and send email using Perl is to use the many modules in the Email::* namespace.
For creating simple email, you should use Email::Simple.
use Email::Simple;
my $email = Email::Simple->create(
header => [
From => 'casey#geeknest.com',
To => 'drain#example.com',
Subject => 'Message in a bottle',
],
body => '...',
);
$email->header_set( 'X-Content-Container' => 'bottle/glass' );
For more complex email (i.e. ones with multiple parts, like file attachments or HTML versions) use Email::MIME.
To send an email, use Email::Sender (actually, in most cases, you can probably get away with Email::Sender::Simple)
use Email::Sender::Simple qw(sendmail);
sendmail($email); # The $email we created in the previous example.
Your first "enhancement" should be to add use strict and use warnings to the top of your program, and declare all your variables using my. That should be your first thought when writing any Perl program.
As for sending an email, you don't say what it is you want to send, but I suggest you use the MIME::Lite module.
This script works on localhost with the -w switch but not without. It also works when use strict and use warning are active.
apache2/error.log:
without switch (aborted script):
(2)No such file or directory: exec of ... failed
with the switch I get:
Use of uninitialized value $email_flag in string ne ...
which looks initialised to me.
On the live web server neither one works. Perl is new to me, but I know some BASH and PHP.
I run Debian Lenny, Apache2, Perl 5.10.
#!/usr/bin/perl -w
$| = 1;
my $mailprog = '/usr/sbin/sendmail'; # where the mail program lives
my $to = "not\#for.you"; # where the mail is sent
my ($command,$email,#pairs,$buffer,$pair,$email_flag) ;
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
#pairs = split(/&/, $buffer);
foreach $pair (#pairs) {
# Split the pair up into individual variables. #
my($name, $value) = split(/=/, $pair);
# Decode the form encoding on the name and value variables. #
$name =~ tr/+/ /;
$name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
# If they try to include server side includes, erase them, so they
# aren't a security risk if the html gets returned. Another
# security hole plugged up.
$value =~ s/<!--(.|\n)*-->//g;
## print "Name of form element is $name with value of $value \n";
if ($name eq 'email') {
$email = $value;
}
if ($name eq 'command') {
$command = $value;
}
}
if ($email =~ /(#.*#)|(\.\.)|(#\.)|(\.#)|(^\.)/ ||
$email !~ /^.+\#(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,3}|[0-9]{1,3})(\]?)$/ ) {
$email_flag = "ERROR";
}
my $urlcommand = $command;
if ($command eq 'Subscribe') {
$command = "SUBSCRIBE rpc-news";
}
if ($command eq 'Unsubscribe') {
$command = "UNSUBSCRIBE rpc-news";
}
if ($command eq 'Suspend') {
$command = "SET rpc-news NOMAIL";
}
if ($command eq 'Resume') {
$command = "SET rpc-news MAIL";
}
my $getInfo = '';
print "Content-Type: text/html\n";
if ($email_flag ne "ERROR") {
open(MAIL,"|$mailprog -t");
print MAIL "To: $to\n";
print MAIL "From: $email\n";
print MAIL "Subject: [rpc-news] $command \n";
print MAIL "Reply-to: $email \n";
print MAIL "$command \n";
print MAIL "EXIT \n";
close (MAIL);
$getInfo = "?result=good";
}
if ($email_flag eq "ERROR") {
$getInfo = "?result=bad";
}
my $rootURL= $ENV{'SERVER_NAME'};
my $url = "http://${rootURL}/thank_you.html${getInfo}&action=${urlcommand}";
print "Location: $url\n\n";
Did you create your script on a Windows machine and upload it to a Linux server without fixing the line endings? Without the -w switch, the shebang line may look like "#!/usr/bin/perl\r", so the system goes looking for a program named "perl\r" (or however the line ending looks). With the -w switch, "#!/usr/bin/perl" doesn't have an indecipherable line ending stuck to it. Instead, that gets stuck to -w where it doesn't cause failure.
I thought there was a perlfaq about this, but I can't seem to find it in the docs at the moment.
Update: I found it over on PerlMonks, in a really old Q&A topic that seems unrelated until you read the body of the message: Answer: How to get rid of premature end of script headers. Yeah, I know, if you were just browsing threads you wouldn't even stop on that one. But here's the text of the post:
If you developed this script on
Windows, it's possible that the script
file has non-UNIX line endings. (The
perl interpreter can handle them, but
the shebang line is interpreted by the
shell, and is not tolerant of
incorrect line endings.) If this is
the problem, the script may terminate
with an error right at the shebang
line.
Use of uninitialized value $email_flag in string ne ...
which looks initialised to me.
if ($email =~ /(#.*#)|(\.\.)|(#\.)|(\.#)|(^\.)/ ||
$email !~ /^.+\#(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,3}|[0-9]{1,3})(\]?)$/
) {
$email_flag = "ERROR";
}
$email_flag only gets initialized here if the pattern matches - otherwise it's left undefined. You could add an else clause to ensure it gets initialized no matter what.
I would not use that code, it doesn't use CGI.pm (or CGI::Simple ...)
Get "TFMail -- Improved Form Mail" from "nms - web programs written by experts"
Its simple to install, and its written well ( it uses CGI ...)