I use Mail::IMAPClient
Have some variables
$body = $imap->body_string($msg);
$header = $imap->message_string($msg);
$body contains body of message, but $header contains header and body of message. I have not found a method in IMAPClient, who get only message header.
I need delete body from $header. Split $body and $header bad variant, because body can be very big. Body and header separates the empty string, but I do not know how to use it.
Please have a look at http://gagravarr.org/code/test-imap-headers.pl
It suggests the Mail::IMAPClient package supports/supported the 'keyword' "ALL" to get all headers at once:
my %headers = %{ $imap->parse_headers( $msg, "ALL" ) };
for my $h ( keys %headers ) {
my #hdrs = #{ $headers{$h} };
print "$h (" . scalar #hdrs . " entries)\n";
foreach (#hdrs) { print "\t$_\n"; }
}
Related
Here is the error message I am receiving when I try to run the following Perl code. Any ideas what causing this? It appears it does not like the API=Verify, but it was the only name for the API which returns a 9 digit zip code I could find.
80040B1AAPI Authorization failure. is not a valid API name for this
protocol.USPSCOM::DoAuth
# Perl subroutine for POST Request
#########
sub FindTracking() {
$saddress="60 Passional Way";
$scity="Burnsville";
$szip="27690";
$sstate="NC";
print "start of tracking...<br>";
$queryString = qq~
<?xml version="1.0"?>
https://secure.shippingapis.com/ShippingAPI.dll?API=Verify&XML=
<AddressValidateRequest USERID="xxxxxxx">
<Revision>1</Revision>
<Address ID="0">
<Address1></Address1>
<Address2>$saddress</Address2>
<City>$scity</City>
<State>$sstate</State>
<Zip5>$szip</Zip5>
<Zip4></Zip4>
</Address>
</AddressValidateRequest>
<?xml version="1.0"?>
<AddressValidateResponse><Address ID="0">
<Address2></Address2><City></City><State></State><Zip5></Zip5>
<Zip4></Zip4></Address></AddressValidateResponse>
<Error>
<Number></Number>
<Source></Source>
<Description></Description>
<HelpFile></HelpFile>
<HelpContext></HelpContext>
</Error>
~;
# Instantiate the user agent and set our agent string
$userAgent = new LWP::UserAgent;
$userAgent->agent( 'USPS' );
$queryString =~ s/ /\%20/ig;
$request = new HTTP::Request( 'POST',
'https://secure.shippingapis.com/ShippingAPI.dll' );
# Set the content type
$request->content_type( 'text/xml' );
# Set the query string
$request->content( $queryString );
# Make the request
$response = $userAgent->request( $request );
print $response->content();
# Check the status of the request
if ( $response->is_success ) {
$content = $$response{ "_content" };
$TrackingNumber = "";
($success) = $content =~ /\<AddressValidateRequest\>(.*)\
<\/AddressValidateRequest\>/;
print "<br><br>==>some $content<br>";
if ($success eq "Success") {
($TrackingNumber)= $content =~ /\<Zip4\>(.*)\<\/Zip4\>/;
print "here with $TrackingNumber<br>";
}
}
else {
print "<br><br>here with resp=$response<br>req=$request <br>cont
$content";
}
}
To start, you have an invalid query string. Compare what you are doing to the USPS WebTools example and remove what they don't show. Be sure that you are setting your USERID properly (and not using 'xxxxxxx'); an environment variable is handy there.
Or, you can try using the Business::USPS::WebTools module from GitHub. It implements the Zip Code Lookup.
Change your query XML to:
$queryString = qq~
<AddressValidateRequest USERID="xxxxxxxxxxx">
<Revision>1</Revision>
<Address ID="0">
<Address1></Address1>
<Address2>$saddress</Address2>
<City>$scity</City>
<State>$sstate</State>
<Zip5>$szip</Zip5>
<Zip4></Zip4>
</Address>
</AddressValidateRequest>
~;
Then build the request as a GET instead of a POST:
$userAgent = new LWP::UserAgent;
$userAgent->agent( 'USPS' );
$url = "https://secure.shippingapis.com/ShippingAPI.dll?API=Verify&XML=$queryString";
$request = new HTTP::Request( 'GET', $url );
I am creating a page that sends the response from contact form within mail but reply-to is not working (the variable i am using is having value, but is not added within headers)
here's my code:
<?php
//$uname=$_REQUEST['uname'];
if(isset($_REQUEST['name']))
{
$name=$_REQUEST['name'];
}
if(isset($_REQUEST['email']))
{
$email=$_REQUEST['email'];
}
if(isset($_REQUEST['phone']))
{
$phone=$_REQUEST['phone'];
}
if(isset($_REQUEST['message']))
{
$message=$_REQUEST['message'];
}
// TESTING IF VARIABLES HAVE VALUES
echo "$name $email $phone $message";
// RESULT: TRUE TILL HERE
if($name=="" || $email=="" || $phone=="" || $message=="")
{
header("location:../?inst=invalid");
}
else
{
// ---------------- SEND MAIL FORM ----------------
// send e-mail to ...
$to="mail#example.com";
// Your subject
$subject="$name Contacted you via Contact Form";
// From
$headers = "From: ME <no-reply#example.com>\r\n";
$headers .= 'Reply-To:' . $email . "\r\n";
$headers .= "Return-Path: info#example.com\r\n";
$headers .= "X-Mailer: PHP\n";
$headers .= 'MIME-Version: 1.0' . "\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
print $message;
// send email
$sentmail = mail($to,$subject,$message,$headers);
//$sentmail = mail($to1,$subject,$message,$header);
}
// if your email succesfully sent
if($sentmail){
echo "Mail Sent.";
}
else {
header("location:../landing/?status=verification-pending");
}
?>
Now when i checked headers in my gmail, the value for $email doesn't appear in header information, Also no message is received. All I get is a blank message or may be $message is not printing anything like the same case i am facing with reply-to.
please help me a little with this. Thanks in advance.
Check that you have php warnings and notices enabled. When you are echoing out $name, $email, etc you are doing a redirect using headers after that. If your php notices etc aren't turned on, your header redirect will fail due to having already echoed something, and you won't know that you had invalid input. This is part of the reason you shouldn't echo things out during logic, but should store and out put values later.
Actually there was a little mistake with the above code. I mistakenly added = instead of == while comparison.
This line:
if($name=="" || $email="" || $phone="" || $message="")
Should read as:
if($name=="" || $email=="" || $phone=="" || $message=="")
Since = is for equation and not a condition for comparison ==
Fixed it in the Question
So I'm using PERL and Email::MIME to get an email from gmail. Here is my code:
use Net::IMAP::Simple::Gmail;
use Email::Mime;
# Creat the object that will read the emails
$server = 'imap.gmail.com';
$imap = Net::IMAP::Simple::Gmail->new($server);
# User and password
$user = 'username#gmail.com';
$password = 'passowrd';
$imap->login($user => $password);
# Select the INBOX and returns the number of messages
$numberOfMessages = $imap->select('INBOX');
# Now let's go through the messages from the top
for ($i = 1; $i <= $numberOfMessages; $i++)
{
$top = $imap->top($i);
print "top = $top\n";
$email = Email::MIME->new( join '', #{ $imap->top($i) } );
$body = $email->body_str;
print "Body = $body\n";
}#end for i
When I run it, I get the following error:
can't get body as a string for multipart/related; boundary="----=_Part_6796768_17893472.1369009276778"; type="text/html" at /Library/Perl/5.8.8/Email/Mime.pm line 341
Email::MIME::body_str('Email::MIME=HASH(0x87afb4)') called at readPhoneEmailFeed.pl line 37
If I replace
$body = $email->body_str;
with
$body = $email->body;
I get the output:
Body =
(i.e. empty string)
What's going on here? is there a way for me to get the raw body of the message (->body_raw doesn't work either)? I'm okay with parsing out the body using regex
Email::MIME is not the best documented package I have ever seen.
The body and body_str methods only work on a single mime part. Mostly that would be a simple text message. For anything more complex use the parts method to get each mime component which is itself an Email::MIME object. The body and body_str methods should work on that. An html formatted message will generally have two MIME parts: text/plain and text/html.
This isn't exactly what you want but should be enough to show you what is going on.
my #parts = $email->parts;
for my $part (#parts) {
print "type: ", $part->content_type, "\n";
print "body: ", $part->body, "\n";
}
I want to post russian text on a CP1251 site using LWP::UserAgent and get following results:
# $text="Русский текст"; obtained from command line
FIELD_NAME => $text # result: Г?в г'В?г'В?г'В?г?вєг?вёг?в? Г'В'Г?вчг?вєг'В?г'В'
$text=Encode::decode_utf8($text);
FIELD_NAME => $text # result: Р с?с?с?рєрёр? С'Рчрєс?с'
FIELD_NAME => Encode::encode("cp1251", $text) # result: Г?гіг+г+гЄгёгЏ ГІгҐгЄг+гІ
FIELD_NAME => URI::Escape::uri_escape_utf8($text) # result: D0%a0%d1%83%d1%81%d1%81%d0%ba%d0%b8%d0%b9%20%d1%82%d0%b5%d0%ba%d1%81%d1%82
How can I do this? Content-Type must be x-www-form-urlencoded. You can find similar form here, but there you can just escape any non-latin character using &#...; form, trying to escape it in FIELD_NAME results in 10561091108910891 10901077108210891 (every &, # and ; stripped out of the string) or 1056;усский текст (punctuation characters at the beginning of the string are stripped out) depending on what the FIELD_NAME actually is.
UPDATE: Anybody knows how to convert the following code so that it will use LWP::UserAgent::post function?
my $url=shift;
my $fields=shift;
my $request=HTTP::Request->new(POST => absURL($url));
$request->content_type('application/x-www-form-urlencoded');
$request->content_encoding("UTF-8");
$ua->prepare_request($request);
my $content="";
for my $k (keys %$fields) {
$content.="&" if($content ne "");
my $c=$fields->{$k};
eval {$c=Encode::decode_utf8($c)};
$c=Encode::encode("cp1251", $c, Encode::FB_HTMLCREF);
$content.="$k=".URI::Escape::uri_escape($c);
}
$request->content($content);
my $response=$ua->simple_request($request);
This code actually solves the problem, but I do not want to add the third request wrapper function (alongside with get and post).
One way around it appears to be (far from the best, I think) to use recode system command if you have it avialable. From http://const.deribin.com/files/SignChanger.pl.txt
my $boardEncoding="cp1251"; # encoding used by the board
$vals{'Post'} = `fortune $forunePath | recode utf8..$boardEncoding`;
$res = $ua->post($formURL,\%vals);
Another approach seems to be in http://mail2lj.nichego.net/lj.txt
my $formdata = $1 ;
my $hr = ljcomment_string2form($formdata) ;
my $req = new HTTP::Request('POST' => $ljcomment_action)
or die "new HTTP::Request(): $!\n" ;
$hr->{usertype} = 'user' ;
$hr->{encoding} = $mh->mime_attr('content-type.charset') ||
"cp1251" ;
$hr->{subject} = decode_mimewords($mh->get('Subject'));
$hr->{body} = $me->bodyhandle->as_string() ;
$req->content_type('application/x-www-form-urlencoded');
$req->content(href2string($hr)) ;
my $ljres = submit_request($req, "comment") ;
if ($ljres->{'success'} eq "OK") {
print STDERR "journal updated successfully\n" ;
} else {
print STDERR "error updating journal: $ljres->{errmsg}\n" ;
send_bounce($ljres->{errmsg}, $me, $mh->mime_attr("content-type.charset")) ;
}
Use WWW::Mechanize, it takes care of encoding (both character encoding and form encoding) automatically and does the right thing if a form element's accept-charset attribute is set appropriately. If it's missing, the form defaults to UTF-8 and thus needs correction. You seem to be in this situation. By the way, your example site's encoding is KOI8-R, not Windows-1251. Working example:
use utf8;
use WWW::Mechanize qw();
my $message = 'Русский текст';
my $mech = WWW::Mechanize->new(
cookie_jar => {},
agent => 'Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/533.9 SUSE/6.0.401.0-2.1 (KHTML, like Gecko)',
);
$mech->get('http://zhurnal.lib.ru/cgi-bin/comment?COMMENT=/z/zyx/index_4-1');
$mech->current_form->accept_charset(scalar $mech->response->content_type_charset);
$mech->submit_form(with_fields => { TEXT => $message });
HTTP dump (essential parts only):
POST /cgi-bin/comment HTTP/1.1
Content-Length: 115
Content-Type: application/x-www-form-urlencoded
FILE=%2Fz%2Fzyx%2Findex_4-1&MSGID=&OPERATION=store_new&NAME=&EMAIL=&URL=&TEXT=%F2%D5%D3%D3%CB%C9%CA+%D4%C5%CB%D3%D
These functions solve the issue (first for posting application/x-www-form-urlencoded data and second for multipart/form-data):
#{{{2 postue
sub postue($$;$) {
my $url=shift;
my $fields=shift;
my $referer=shift;
if(defined $referer and $referer eq "" and defined $fields->{"DIR"}) {
$referer=absURL($url."?DIR=".$fields->{"DIR"}); }
else {
$referer=absURL($referer); }
my $request=HTTP::Request->new(POST => absURL($url));
$request->content_type('application/x-www-form-urlencoded');
$request->content_encoding("UTF-8");
$ua->prepare_request($request);
my $content="";
for my $k (keys %$fields) {
$content.="&" if($content ne "");
my $c=$fields->{$k};
if(not ref $c) {
$c=Encode::decode_utf8($c) unless Encode::is_utf8($c);
$c=Encode::encode("cp1251", $c, Encode::FB_HTMLCREF);
$c=URI::Escape::uri_escape($c);
}
elsif(ref $c eq "URI::URL") {
$c=$c->canonical();
$c=URI::Escape::uri_escape($c);
}
$content.="$k=$c";
}
$request->content($content);
$request->referer($referer) if(defined $referer);
my $i=0;
print STDERR "Doing POST request to url $url".
(($::o_verbose>2)?(" with fields:\n".
::YAML::dump($fields)):("\n"))
if($::o_verbose>1);
REQUEST:
my $response=$ua->simple_request($request);
$i++;
my $code=$response->code;
if($i<=$o_maxtries and 500<=$code and $code<600) {
print STDERR "Failed to request $url with code $code... retrying\n"
if($::o_verbose>2);
sleep $o_retryafter;
goto REQUEST;
}
return $response;
}
#{{{2 postfd
sub postfd($$;$) {
my $url=absURL(shift);
my $content=shift;
my $referer=shift;
$referer=absURL($referer) if(defined $referer);
my $i=0;
print STDERR "Doing POST request (form-data) to url $url".
(($::o_verbose>2)?(" with fields:\n".
::YAML::dump($content)):("\n"))
if($::o_verbose>1);
my $newcontent=[];
while(my ($f, $c)=splice #$content, 0, 2) {
if(not ref $c) {
$c=Encode::decode_utf8($c) unless Encode::is_utf8($c);
$c=Encode::encode("cp1251", $c, Encode::FB_HTMLCREF);
}
push #$newcontent, $f, $c;
}
POST:
my $response=$ua->post($url, $newcontent,
Content_type => "form-data",
((defined $referer)?(referer => $referer):()));
$i++;
my $code=$response->code;
if($i<=$o_maxtries and 500<=$code and $code<600) {
print STDERR "Failed to download $url with code $code... retrying\n"
if($::o_verbose>2);
sleep $o_retryafter;
goto POST;
}
return $response;
}
I have some URLs like http://anytext.a.abs.com
In these, 'anytext' is the data that is dynamic. Rest of the URL will remain same in every case.
I'm using the following code:
$url = "http://anytext.a.abs.com";
my $request = new HTTP::Request 'GET', $url;
my $response = $ua->request($request);
if ($response->is_success)
{
function......;
}
Now, how can I parse a URL that has dynamic data in it?
Not sure but is this close to what you're after?:
for my $host qw(anytext someothertext andanother) {
my $url = "http://$host.a.abs.com";
my $request = new HTTP::Request 'GET', $url;
my $response = $ua->request($request);
if ($response->is_success)
{
function......;
}
}
Something like this maybe?
Otherwise, you can use the URI class to do url manipulation.
my $protocol = 'http://'
my $url_end = '.a.abs.com';
$url = $protocol . "anytext" . $url_end;
my $request = new HTTP::Request 'GET', $url;
my $response = $ua->request($request);
if ($response->is_success)
{
function......;
}
I think this is probably enough:
# The regex specifies a string preceded by two slashes and all non-dots
my ( $host_name ) = $url =~ m{//([^.]+)};
And if you want to change it:
$url =~ s|^http://\K([^.]+)|$host_name_I_want|;
Or even:
substr( $url, index( $url, $host_name ), length( $host_name ), $host_name_I_want );
This will expand the segment sufficiently to accommodate $host_name_I_want.
Well, like you would parse any other data: Use the information you have about the structure.
You have a protocol part, followed by "colon slash slash", then the host followed by optional "colon port number" and an optional path on the host.
So ... build a little parser that extracts the information you are after.
And frankly, if you are only hunting for "what exactely is 'anytext' here?", a RegEx of this form should help (untested; use as guidance):
$url =~ m/http\:\/\/(.*).a.abs.com/;
$subdomain = $1;
$do_something('with', $subdomain);
Sorry if I grossly misunderstood the problem at hand. Please explain what you mean with 'how can I parse a URL that has dynamic data in it?' in that case :)