Is it possible to only download IMAP messages without attachments? - ruby

I want to process a bunch of my emails with Net::IMAP, but I want to skip the ones with attachments because they take too long. Any hints? Ultimately, I'm looking to download all the text and HTML content of emails, as fast as possible. Right now, I'm fetching one UID at a time, and parallelizing it with 15 processes (the max GMAIL allows), but I'm hitting a snag on the messages with attachments.
imap = Net::IMAP.new('imap.gmail.com', 993, usessl = true, certs = nil, verify = false)
imap.authenticate('XOAUTH2', user.email, user.token)
mailbox = "[Gmail]/All Mail"
imap.select(mailbox)
message_id = 177
imap.fetch(message_id,'RFC822')[0].attr['RFC822'] # this fetches the whole message, including attachment, which makes it slow...

imap rfc does not provide any such implementations but as an alternative there could be a possible hack, assuming that the mail is following the rfc standard, fetch the entire mail header of mail and check for content type if it is multipart/mixed then for sure an attachment exists in a mail.
On content type you can get more info at http://en.wikipedia.org/wiki/MIME
This is just one of possible ways to find an attachment.

Related

Too Much time taken by phpmailer library

I am creating a script to send 10 files to different recipients daily basis. These files size can be upto 15 MB. The phpmailer is taking lot of time 10 to 15 min. so it become unusable to me. I am using gmail smtp.
//Server settings
//$mail->SMTPDebug = SMTP::DEBUG_SERVER; // Enable verbose debug output
$mail->SMTPDebug = 0; //Alternative to above constant
$mail->isSMTP(); // Send using SMTP
$mail->Host = 'smtp.gmail.com'; // Set the SMTP server to send through
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = 'rmudelhi#gmail.com'; // SMTP username
$mail->Password = 'rainfall2016'; // SMTP password
//$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` encouraged
$mail->SMTPSecure= 'tls';
$mail->Port = 587;
Can someone help me to improve this?
It's not that PHPMailer is slow, it's that you're trying to perform an inherently slow operation during page load; you're transferring around 150 megabytes per recipient, which is never going to happen quickly.
Do not do the email sending during the page load - save the fact that you need to do the send in your database or queue, and process the send asynchronously.
The easiest way to do this is to use a cron job to pick up the send tasks and run them.
Alternatively, do not send the files by email, but send a message containing links that point at them, so that the recipients can download them via HTTP more efficiently. Email is simply not an efficient method for sending large files.

How would I design this scenario in Twilio?

I'm working on a YRS 2013 project and would like to use Twilio. I already have a Twilio account set up with over $100 worth of funds on it. I am working on a project which uses an external API and finds events near a location and date. The project is written in Ruby using Sinatra (which is going to be deployed to Heroku).
I am wondering whether you guys could guide me on how to approach this scenario: a user texts to the number of my Twilio account (the message would contain the location and date data), we process the body of that sms, and send back the results to the number that asked for them. I'm not sure where to start; for example if Twilio would handle some of that task or I would just use Twilio's API and do checking for smss and returning the results. I thinking about not using a database.
Could you guide me on how to approach this task?
I need to present the project on Friday; so I'm on a tight deadline! Thanks for our help.
They have some great documentation on how to do most of this.
When you receive a text you should parse it into the format you need
Put it into your existing project and when it returns the event or events in the area you need to check how long the string is due to a constraint that twilio has of restricting messages to 160 characters or less.
Ensure that you split the message elegantly and not in the middle of an event. If you were returned "Boston Celtics Game", "The Nut Cracker Play". you want to make sure that if both events cannot be put in one message that the first message says "Boston Celtics Game, Another text coming in 1 second" Or something similar.
In order to receive a text message from a mobile device, you'll have to expose an endpoint that is reachable by Twilio. Here is an example
class ReceiveTextController < ActionController
def index
# let's pretend that we've mapped this action to
# http://localhost:3000/sms in the routes.rb file
message_body = params["Body"]
from_number = params["From"]
SMSLogger.log_text_message from_number, message_body
end
end
In this example, the index action receives a POST from Twilio. It grabs the message body, and the phone number of the sender and logs it. Retrieving the information from the Twilio POST is as simple as looking at the params hash
{
"AccountSid"=>"asdf876a87f87a6sdf876876asd8f76a8sdf595asdD",
"Body"=> body,
"ToZip"=>"94949",
"FromState"=>"MI",
"ToCity"=>"NOVATO",
"SmsSid"=>"asd8676585a78sd5f548a64sd4f64a467sg4g858",
"ToState"=>"CA",
"To"=>"5555992673",
"ToCountry"=>"US",
"FromCountry"=>"US",
"SmsMessageSid"=>"hjk87h9j8k79hj8k7h97j7k9hj8k7",
"ApiVersion"=>"2008-08-01",
"FromCity"=>"GRAND RAPIDS",
"SmsStatus"=>"received",
"From"=>"5555992673",
"FromZip"=>"49507"
}
Source

Selecting an outgoing mail message programmatically

Here's what I'm attempting to do: Let's assume that you are in mail and create a New blank mail message, then enter some data into it, such as body copy, etc. (in my case, the message was created through scripting bridge using the "Mail Contents of this Page" from safari... the main purpose of this process for my application.)
From my application, I want to select that message and assign it to:
MailOutgoingMessage *myMessage;
so that I can programmatically add recipients. I've tried several ways of doing this which seemed logical, but so far I haven't found the right combination, and the header file doesn't seem to be very clear to me (I'm new to scripting bridge.)
My initial thought was to try this:
mailMessage = [[mail outgoingMessages] lastObject];
Which should grab the last outgoing message created. It seems to work in that I am able to add recipients to mailMessage (though there have been a few times that I received unexpected results when multiple outgoing messages exist, such as adding the recipients to the wrong message) but attempting to log the subject line of the message:
NSLog(#"Subject = %#",[mailMessage subject]);
always returns NULL even though there is a subject clearly viewable in the subject field of the message. NULL is returned for any other parameter as well.
I'm gathering it must be a problem with my assignment to mailMessage above, because the only time I receive a NULL for message properties (or receive unexpected results) is if I try to point mailMessage to an existing outgoing message. If I create the mail message with scripting bridge, then I can retrieve all of the properties correctly.
Does anyone understand the hierarchy of the Mail scripting enough to tell me why I am getting NULLs for the parameters using the above assignment for mailMessage? What would the simplest way be go grab my message so that I can add recipients and later call the:
[myMessage send];
method? Any insight would be helpful. I've spent a week going through the mail.h header file and am quite literally at a loss as to what else to try at this point.
There's no way to (send, get or set the properties of the outgoing message) that the user or Safari has created.
It's a bug (it stopped working since Mac OS X 10.4), or some privacy/security considerations.

Ruby Large HTML emails getting error, limit to header size

def mailTo(subject,msg,folks)
begin
Net::SMTP.start('localhost', 25) do |smtp|
smtp.send_message "MIME-Version: 1.0\nContent-type: text/html\nSubject: #{subject}\n#{msg}\n#{DateTime.now}\n", 'person#domain.com', folks
end
rescue => e
puts "Emailing Sending Error - #{e}"
end
end
when the HTML is VERY large I get this exception
Emailing Sending Error - 552 5.6.0 Headers too large (32768 max)
how can i get a larger html above max to work with Net::SMTP in Ruby
This might not be a restriction imposed by the library, but rather a restriction imposed by the service you are using to send. It kinda depends on just how huge of an HTML file we're talking about here, but your mail server may simply not let you send things that large. This probably can not be addressed with simple programming; you're gonna have to come up with a creative solution, like sending through a different service or breaking up the message.
I believe that this is a problem with SMTP and sending that email/message. Try reducing the number of people you send a message to at one time. For example, if you are sending a message to 500 people at once, then maybe send the message to 50 different people at a time instead (sending the message ten times).
2 quick observations:
"552 5.6.0 Headers too large"
this is a SMTP error message. It's coming from your SMTP server, not your code. Your code is just bubbling it up.
Headers are supposed to be seperated by "\r\n", not just "\n". Try fixing that part of your code.
I ran into this issue today. I resolved it by adding body tags to the HTML email.
Without those everything was going into the header.
MIME-Version: 1.0
Content-type: text/html
Subject: Nifty Report
<body>
<h1>some junk</h1>
</body>

CDO.Message - to many connections

I am writing a newsletter application using CDO.Message. But get an error back that we have to many connections. Seems they have a limit of 10 simultaneous connections.
So, is there a way to send several messages on one connection, or disconnect faster?
There is a cdo/configuration/smtpconnectiontimeout parameter, but I think that's more about how long the sender will try.
(If we send,ant it fails, it will succeed again after some minutes, probably meaning that the connection is disconnected).
(We are using CDO partly because we are pulling the HTML message body from a webserver)
Edit:
Public Sub ipSendMail(ByVal toEmail As String, ByVal fromEmail As String, ByVal subject As String, ByVal url As String)
Dim iMsg As Object
Set iMsg = CreateObject("CDO.Message")
iMsg.From = fromEmail
iMsg.To = toEmail
iMsg.Subject = subject
iMsg.CreateMHTMLBody(url)
iMsg.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
iMsg.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "relay.wwwwwwwwww.net"
iMsg.Configuration.Fields.Item_
("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
iMsg.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout") = 0
iMsg.Configuration.Fields.Update()
iMsg.Send()
Set iMsg = Nothing
End Sub
Try to use SMTP instead of CDO, System.Web.Mail.SmtpMail
You could implement a queue, that is processed by a background thread. The background thread would only send one message at a time.
You can store the email in a database table, which is processed by a scheduled task or a stored procedure. Those can again send one mail at a time, and have the advantage of being able to retry, if it goes wrong.
Ordinarily you only need one connection regardless of how many messages you are sending.
Perhaps you are not releasing something that you should be.
Edit: Just a thought, the SMTP server you are sending to, it wouldn't happen to be host on an XP box perhaps for testing reasons?
Edit: Ok so your SMTP server is fine.
What platform is the server supplying the result of the URL?
I know that CDO can be quirky at times, so these are the possible suggestions that I would make:
A queue would probably work the best for you. After that, I would consider setting up a local SMTP server without inbound connection limits that uses a smarthost to queue up your outbound messages. (This could actually be written fairly easily. The "S" is for "Simple" and it actually is.)
If all else fails... You could always roll your own mailer component implementing RFCs 2821 and 2822 (or whatever the latest and greatest RFCs are for SMTP and message format)
EDIT: If the newsletter you are sending out is identical for all recipients, you can address it to a dummy recipient (i.e. newsletter#yourdomain.com) and BCC it to the recipient list (or a subset of the recipient list). Just be careful not to get flagged as unsolicited commercial email. Let your provider know what you are doing. They have to deal with the complaints, and you are the one paying the bill. Letting them know that complaints would be mostly unwarranted (and few and far between) will help to assuage their natural risk aversion.

Resources