Read Gmail XOAUTH mails without marking it read - ruby-on-rails

I'm trying to read email from GMail using gmail-xoauth Gem. I want to read the email and leave its unread status.
First, I tried reading just the header. Works.
imap = Net::IMAP.new('imap.gmail.com', 993, usessl = true, certs = nil, verify = false)
imap.authenticate('XOAUTH2', email, access_token)
imap.select('INBOX')
imap.search(["SINCE", since]).each do |message_id|
msg = imap.fetch(message_id,'RFC822.HEADER')[0].attr['RFC822.HEADER']
mail = Mail.read_from_string msg
puts mail.subject
end
Now, I want to read the body/text of the Email without marking it read.

This maybe be very late but I will leave it here for anyone else that stumbles onto this. If, for what ever reason you want to read the email and leave the flags intake, use:
imap.examine('INBOX')
instead of:
imap.select('INBOX')
From the Net::IMAP doc
Sends a EXAMINE command to select a mailbox so that messages in the mailbox can be accessed. Behaves the same as select(), except that the selected mailbox is identified as read-only.

Based on the documentation you need to use the store method. The documentation mentions:
store(set, attr, flags)
Sends a STORE command to alter data associated with messages in the mailbox, in particular their flags. The set parameter is a number or an array of numbers or a Range object. Each number is a message sequence number. attr is the name of a data item to store: ‘FLAGS’ means to replace the message’s flag list with the provided one; ‘+FLAGS’ means to add the provided flags; and ‘-FLAGS’ means to remove them. flags is a list of flags.
The return value is an array of Net::IMAP::FetchData. For example:
p imap.store(6..8, "+FLAGS", [:Deleted])
#=> [#<Net::IMAP::FetchData seqno=6, attr={"FLAGS"=>[:Seen, :Deleted]}>, \\
#<Net::IMAP::FetchData seqno=7, attr={"FLAGS"=>[:Seen, :Deleted]}>, \\
#<Net::IMAP::FetchData seqno=8, attr={"FLAGS"=>[:Seen, :Deleted]}>]
So you have to remove the :Seen flag
imap.store(message_id, "-FLAGS", [:Seen])

Related

Is there a way to preserve a signature in RDOMail.Reply like MailItem.Reply does?

I tried obtaining the reply to the mail by using RDOMail.Reply method.
However, after inspecting the returned object, I've noticed that the signature is not part of the HTMLBody property, as it is when using method MailItem.Reply (which I'm not using because it throws 0x80004004 (E_ABORT) exception). Also, attachments that would be needed for the signature if it contains images are not preserved as they are with MailItem.Reply.
I've tried applying the signature separately, using Signature object. This adds signature to the HTMLBody, but doesn't use the _MailAutoSig attribute to mark the signature part therefore if I select "Change signature" from Outlook Ribbon, signature doesn't get replaced because Outlook has no way of knowing it is a signature.
Is there a way to obtain reply from RDOMail that would contain signature Outlook knows how to replace?
var rdoMail = session.GetMessageFromID(entryid);
var reply = rdoMail.Reply();
reply.HTMLBody = "";
var Account = session.Accounts.GetOrder(rdoAccountCategory.acMail).Item(1);
var signature = Account.ReplySignature;
signature.ApplyTo(reply, false);
reply.Save();
This is a known issue/case when dealing with Extended MAPI code and it is not related to Redemption only. See Messages that are created outside Outlook do not include the default Outlook email signature for more information.
Your choices are:
Mimic the Outlook behavior by adding all the necessary parts like _MailAutoSig attribute to the message body.
Use the Outlook object model with the Reply method and then getting the Redemption equivalent by using the GetRDOObjectFromOutlookObject method. But as far as I can tell, looking at the exception you get, it is not possible because the code is used from a secondary thread, right?
You can use its RDOAccount object (accessible in any language, including VBA). New message signature name is stored in the 0x0016001F property, reply signature is in 0x0017001F.
You can also use the RDOAccount.ReplySignature and NewSignature properties.
Redemption also exposes RDOSignature.ApplyTo method that takes a pointer to the RDOMail object and inserts the signature at the specified location correctly merging the images and the styles:
set Session = CreateObject("Redemption.RDOSession")
Session.MAPIOBJECT = Application.Session.MAPIOBJECT
set Drafts = Session.GetDefaultFolder(olFolderDrafts)
set Msg = Drafts.Items.Add
Msg.To = "user#domain.demo"
Msg.Subject = "testing signatures"
Msg.HTMLBody = "<html><body>some <b>bold</b> message text</body></html>"
set Account = Session.Accounts.GetOrder(2).Item(1) 'first mail account
if Not (Account Is Nothing) Then
set Signature = Account.NewMessageSignature
if Not (Signature Is Nothing) Then
Signature.ApplyTo Msg, false 'apply at the bottom
End If
End If
Msg.Send

How to use the Gmail API to read the subjects of emails sent from a yahoo group

I'm using the Gmail API with Oauth 2 to read all of my emails and print out the subject and the date, like so:
for m in email_list:
msg = service.users().messages().get(userId="me", id=m["id"], format="full").execute()
header_list = msg["payload"]["headers"]
for i in header_list:
nameindict=i["name"]
if nameindict=="Subject":
print(i["value"])
if nameindict=="Date":
print(i["value"])
this section is pasted into the main() function of the gmail API example, found here:
https://developers.google.com/gmail/api/quickstart/python
However, there's two problems:
-Sometimes, it misses the subject. I checked the full output and found that some outputs didn't have a subject attached, but couldn't find out why.
-This doesn't seem to work with email sent from a Yahoo group. The "full" option returns a jumble of letters and numbers, but no subject or readable date and time sent. Does anyone know if this is possible, and how I can do it?

Google Form/Sheet - Skip blank email google script

This is a similar question to this link, but slightly different:
Skipping blank emails in Google Apps Script Mail Merge
I have a form/sheet set up that, when the users fills out the form, it generates a receipt email (does not contain the form contents as some receipts do) that is then sent to the recipient. However when the user leaves this field blank I get a form trigger error, which is understandable why the script didn't finish. I am trying to figure out how to keep the script from attempting to send an email when the recipient/email field is blank. Unfortunately, making the email field required on the form is not an option since, oddly, not everyone would have an email address (if this were an option I would certainly just require an email address to be entered).
I have tried the following code snippet based on the link provided above.
// Send Email to recipient(s) declared above in #var sendEmail
if (e.values[11] != null) {
var sendEmail = e.values[11]; //email field column
var subject = "subject message";
var body = "body message";
MailApp.sendEmail(sendEmail, subject, body, {
name: "Community Home Health Care",
body: body,
noReply: true,
})
I have also tried instead of
(e.values[11] != null)
using
(e.values[11] != "")
The remaining code I have omitted (goes above what I have shown) simply takes the form field responses and generates a document converted to a PDF which works as expected. The email section also works, just trying to eliminate the failed script emails I get occasionally.
Thanks
First is an assumption that 12 items are passed (0 through 11) and the email is the last item to be passed. If that is the case, then test that the item is defined with:
if(typeof e.values[11] !== 'undefined')
If you are using the Mail Merge Tutorial linked to in the post you linked to, and using the getRowsData() function to get your form responses, you should be able to use the Header of the column containing the email address such as e.values.emailAddress and get:
if(typeof e.values.emailAddress !== 'undefined')
This may vary based on how your data is defined.

How to fetch mail by id with barbushin imap class

I'm currently working on the imap class by barbushin. It's the only php class over the internet I can find regardless to any encoding issue. Thanks to the coder.
I have a list of messages in a table. Each message sending a message id as GET (say $mid). When a link clicked, the page turned into a view page. It should open that message and display the relevant content right? But it is not. Every message has the same content (the 1st content). The code is designed for gmail but I use it for my client. And it's work.
This is a code:
require_once('../ImapMailbox.php');
define('EMAIL', 'my#domain.com');
define('PASSWORD', '*********');
define('ATTACHMENTS_DIR', dirname(__FILE__) . '/attachments');
$mailbox = new ImapMailbox('{imap.gmail.com:993/imap/ssl}INBOX', EMAIL, PASSWORD, ATTACHMENTS_DIR, 'utf-8');
$mails = array();
// Get some mail
$mailsIds = $mailbox->searchMailBox('ALL');
if(!$mailsIds) {
die('Mailbox is empty');
}
$mailId = reset($mailsIds);
$mail = $mailbox->getMail($mailId);
var_dump($mail);
var_dump($mail->getAttachments());
The original is here: https://github.com/barbushin/php-imap
Finally, I found my way home. According to the script there's a line says "mailId". Which is straight forward what is it about.
It was set to the first array by reset(). So the only thing I need to do is extract the message id from it ($mailId is an array of ids). So I simply add an array behind it.
$mailId=$mailsIds[$_GET[uid]];
While $_GET[uid] is a message id sent from a previous page.

While processing an email reply how can I ignore any email client specifics & the history?

I have a rails application which processes incoming emails via IMAP. Currently a method is used that searches the parts of a TMail object for a given content_type:
def self.search_parts_for_content_type(parts, content_type = 'text/html')
parts.each do |part|
if part.content_type == content_type
return part.body
else
if part.multipart?
if body = self.search_parts_for_content_type(part.parts, content_type)
return body
end
end
end
end
return false
end
These emails are generally in response to a html email it sent out in the first place. (The original outbound email is never the same.) The body text the method above returns contains the full history of the email and I would like to just parse out the reply text.
I'm wondering whether it's reasonable to place some '---please reply above this line---' text at the top of the mail as I have seen in a 37 signals application.
Is there another way to ignore the client specific additions to the email, other than write a multitude of regular expressions (which I haven't yet attempted) for each and every mail client? They all seem to tack on their own bit at the top of any replies.
I have to do email reply parsing on a project I'm working on right now. I ended up using pattern matching to identify the response part, so users wouldn't have to worry about where to insert their reply.
The good news is that the implementation really isn't too difficult. The hard part is just testing all the different email clients and services you want to support and figuring out how to identify each one. Generally, you can use either the message ID or the X-Mailer or Return-Path header to determine where an incoming email came from.
Here's a method that takes a TMail object and extracts the response part of the message and returns that along with the email client/service it was sent from. It assumes you have the original message's From: name and address in the constants FROM_NAME and FROM_ADDRESS.
def find_reply(email)
message_id = email.message_id('')
x_mailer = email.header_string('x-mailer')
# For optimization, this list could be sorted from most popular to least popular email client/service
rules = [
[ 'Gmail', lambda { message_id =~ /.+gmail\.com>\z/}, /^.*#{FROM_NAME}\s+<#{FROM_ADDRESS}>\s*wrote:.*$/ ],
[ 'Yahoo! Mail', lambda { message_id =~ /.+yahoo\.com>\z/}, /^_+\nFrom: #{FROM_NAME} <#{FROM_ADDRESS}>$/ ],
[ 'Microsoft Live Mail/Hotmail', lambda { email.header_string('return-path') =~ /<.+#(hotmail|live).com>/}, /^Date:.+\nSubject:.+\nFrom: #{FROM_ADDRESS}$/ ],
[ 'Outlook Express', lambda { x_mailer =~ /Microsoft Outlook Express/ }, /^----- Original Message -----$/ ],
[ 'Outlook', lambda { x_mailer =~ /Microsoft Office Outlook/ }, /^\s*_+\s*\nFrom: #{FROM_NAME}.*$/ ],
# TODO: other email clients/services
# Generic fallback
[ nil, lambda { true }, /^.*#{FROM_ADDRESS}.*$/ ]
]
# Default to using the whole body as the reply (maybe the user deleted the original message when they replied?)
notes = email.body
source = nil
# Try to detect which email service/client sent this message
rules.find do |r|
if r[1].call
# Try to extract the reply. If we find it, save it and cancel the search.
reply_match = email.body.match(r[2])
if reply_match
notes = email.body[0, reply_match.begin(0)]
source = r[0]
next true
end
end
end
[notes.strip, source]
end
I think you will be stuck on this one. I have been doing some stuff with emails myself in TMail recently, and what you will generally find is that an email that has an HTML part is generally structured like:
part 1 - multipart/mixed
sub part 1 - text/plain
sub part 2 - text/html
end
The email clients I have played with Outlook and Gmail both generate replies in this format, and they just generally quote the original email inline in the reply. At first I though that the 'old' parts of the original email would be separate parts, but they are actually not - the old part is just merged into the reply part.
You could search the part for a line that begins 'From: ' (as most clients generally place a header at the top of the original email text detailing who sent it etc), but its probably not guaranteed.
I don't really see anything wrong with a --- please reply above this line --- generally, its not that invasive, and could make things a lot simpler.

Resources