Archive Gmail messages in Mail.app

@benin,
Try to add following to the end (before the “end repeat”) of your script in post 1:

synchronize with theAccount

Hmm… it didn’t do the trick. I suspect AppleScript isn’t actually moving the Gmail messages since they’re already in [Gmail]/All Mail for whatever reason.

Maybe there’s something wrong with my Gmail account settings or local mailbox if move {x} to mailbox “[Gmail]/All Mail” actually archives Gmail messages well for everyone.

I’m seeing the exact same behaviour you are @benyn. Move to Archive seems to do nothing for Gmail currently. I created another folder, “Archived”, and moving there also seems to do nothing.

Surprisingly, using “Move” instead of “Archive” in the actual Apple Mail UI also doesn’t work. The message disappears and immediately reappears in the inbox. Synchronize makes no difference.

Only the actual Archive button in Mail.app works. So I guess Apple Mail has some custom code to remove the Inbox label from the message when it’s a Google email, but that this functionality isn’t exposed or used properly with Move.

I also tried using Apple Script to remove the message specifically from the inbox (after first doing a move to my archived folder), but the message ends up only in the bin. Switching the order, removing first and then moving, seems to do nothing. The message remains in the bin, possibly because it changes Apple Script ID after the first action so the handle on it has been lost.

1 Like

I’m relieved to know that I’m not the only one experiencing this problem, @aljungberg . Greatly appreciate your reply. I hadn’t tried to “Move” messages in Apple Mail UI, but exactly like you said, it doesn’t work, either. The message disappears and immediately reappears.

Guess we’ll have to wait until Apple extends the Gmail-specific code used for the Archive action to the Move action. Given the Move action seems to still work for everyone else on the thread, maybe this is a recent problem (macOS Ventura 13.3 broke many little things that used to work well for me) that can be patched up in the coming updates or macOS 14. Fingers crossed.

Yes, you might be right. I made one more discovery: “Archived” is apparently a special name for Google so that was a poor choice for my experiments.

Using Gmail’s web UI I created another folder named Archived_ instead, and this new folder is less buggy in the Mail.app UI. I can move a message from the inbox to this folder by drag and drop and it will disappear from the inbox and appear there instead. Exactly what I wanted… except it doesn’t work the same via AppleScript, sigh.

With AppleScript, moving the mail to Archived_ just makes it appear in both folders. In the Gmail UI I can confirm the email takes on the new label and keeps the old label as well.

We got so close to a workaround!

Okay after much trial and error here’s a workaround that seems to work in my testing: first move the message to the bin, then move it to archive. I don’t know if it’s Apple Mail or Google that treats the bin in a different way, but this seems to clear the Inbox label. The only quirk is that once the message is in the bin, it loses its identity so you have to select it again to move it back out.

using terms from application "Mail"
	tell application "Mail"
		set the_messages to (get selection)
		repeat with a_message in the_messages
			set message_id to message id of a_message
			set the_account to a_message's mailbox's account
			set trash_mbox to mailbox "Trash" of the_account
			move a_message to trash_mbox
			set new_message to (first message of trash_mbox whose message id is message_id)
			move new_message to mailbox "Archive" of the_account
		end repeat
	end tell
end using terms from
2 Likes

@aljungberg,

You are trying to archive what is already being archived by Mail.app in the mailbox “[Gmail]/All Mail” of the “Gmail” account when a new message arrives, automatically.

Mailbox “[Gmail]/All Mail” of the “Gmail” account is the archive.

Another thing is that the new message remains duplicated in the “INBOX” mailbox of the “Gmail” account too. That is, you just need to destroy the duplicate of the selected message, located in the INBOX.
.

tell application "Mail"
	repeat with aMessage in (get selection)
		delete (1st message of mailbox "INBOX" of account "Gmail" whose id is id of aMessage)
	end repeat
end tell

That is an absolutely brilliant solution, @aljungberg ! It worked perfectly. It’s also quite amazing that it is the only Inbox label that gets cleared; other labels attached by Gmail filters remain intact.

Using the script below (which I also included in my original post), I saw that Apple Mail correctly recognizes the parent mailbox of Gmail messages that belong to Drafts, Junk (Spam), and Trash. For all the other messages, including those in the Sent mailbox, the script returns “All Mail” as the messages’ parent mailbox name.

To test this hypothesis, I replaced “Trash” with “Drafts” in your script and the script successfully moved the messages. But I also got a warning message titled “Online Status”: “The following alerts are from the IMAP server for “Gmail”: Only Drafts can exist in the Drafts folder (Failure)”. So “Trash” seems to be the only viable option for this workaround. Thanks so much @aljungberg !

set mailboxNames to {}
tell application "Mail"
	set selectedMessages to selection
	repeat with m in selectedMessages
		copy m's mailbox's name to end of mailboxNames
	end repeat
end tell
return mailboxNames

I tried your script, @KniazidisR , but it deletes the message entirely rather than removing it only from Inbox. If the message in Inbox was indeed a duplicate, I’d have expected your script to remove the message from Inbox while keeping the message in “[Gmail]/All Mail” a.k.a. “Archive” intact. I might have misunderstood the intended behavior of your script, so please correct me if I’m mistaken.

I agree it’s not the most elegant solution, but I believe it’s the best workaround available given the limitations of the Move command and also the oddity around how Mail.app treats Gmail messages. I suspect that the oddity stems from the fact that Gmail uses labels instead of folders/mailboxes, while Mail.app is built on the assumption that a message belongs to a single mailbox.

I made a mistake, my apologies. Apparently, the proposed solution is really the only one so far.

1 Like

For all the other messages, including those in the Sent mailbox, the script returns “All Mail” as the messages’ parent mailbox name.

Yep, I can confirm that too. And as you noted, there’s a special “INBOX” folder too. I can access it via AppleScript but I wasn’t able to get the message to act any differently by trying to select it from that mailbox instead of the normal Apple Mail inbox. No matter how you get the message, it thinks it’s in All Mail.

Which probably explains why moving a message from the Inbox to a custom folder like Banana doesn’t work. I bet the Banana label is successfully added but then Mail tries to remove the All Mail label rather than Inbox, and I bet you can’t remove All Mail (by definition). So that turns into a “do nothing” operation. End result is that you add a label and remove no label, which is what I saw with my custom archive folder.

So that’s an alternative explanation for how my terrible hack works: maybe Trash is the one label (besides Junk and Drafts that you found) that makes an email no longer be considered All Mail. So now Apple Mail doesn’t get confused by this unremovable label and actually removes the right thing.

It’s also quite amazing that it is the only Inbox label that gets cleared; other labels attached by Gmail filters remain intact.

Yes those labels seem even more special? I can’t clear them in the Gmail UI, but I can delete Inbox and other labels I’ve added.

the oddity around how Mail.app treats Gmail messages. I suspect that the oddity stems from the fact that Gmail uses labels instead of folders/mailboxes, while Mail.app is built on the assumption that a message belongs to a single mailbox.

Yes, I think you’re right. Now that you say it, I’m forming a vague mental outline of what might be happening. Apple Mail probably has some custom support for Gmail so it knows an email can have multiple labels. That’s how the Inbox works correctly; Mail can correctly determine that the message does not only belong to All Mail but also Inbox, in the context of IMAP. So it can then do the right thing with Message > Archive.

But (maybe) they never updated the AppleScript integration to expose this internal state and instead simplify it so every reference to a message is keyed on a single mailbox. One you can’t choose. This way the move operation becomes non-functional in this context since the operation of moving probably is implemented as “remove the source mailbox label and add the destination mailbox label”. If the parent mailbox isn’t correctly recognised as Inbox, and instead is All Mail, which can’t actually be untagged, move effectively transforms into “duplicate”.

Still doesn’t quite explain how the hack removes the Inbox label.

You are trying to archive what is already being archived by Mail.app in the mailbox “[Gmail]/All Mail” of the “Gmail” account when a new message arrives, automatically.

I’m not sure what you mean here. Obviously we’re not trying to archive messages that are already archived! We’re trying to get rid of the Inbox label, if I understand how Gmail works.

Mailbox “[Gmail]/All Mail” of the “Gmail” account is the archive.

Sure, I think we’re all in agreement there.

Another thing is that the new message remains duplicated in the “INBOX” mailbox of the “Gmail” account too. That is, you just need to destroy the duplicate of the selected message, located in the INBOX.

Right so @benyn has already answered this, but just to add to this now that we have a little more understanding. Why isn’t this possible? There seems to be no way to use AppleScript to do it, given the apparent 1-1 maibox->message relationship exposed there. You can’t specify which mailbox to delete a message from, it just goes to the bin from all mailboxes. In testing, the message always “thinks” it belongs to All Mail in AppleScript, and deleting a message from All Mail is the same as just deleting it.

set m2 to (first message of (mailbox "INBOX" of the_account) whose message id is message_id)
set m3 to (first message of (mailbox "[Gmail]/All Mail" of the_account) whose message id is message_id)

m2 and m3 are the same object, indistinguishable. From the Replies tab:

get message 1 of mailbox "INBOX" of account id "..." whose message id = "1234"
		--> message id 746767 of mailbox "[Gmail]/All Mail" of account id "..."
	get message 1 of mailbox "[Gmail]/All Mail" of account id "..." whose message id = "1234"
		--> message id 746767 of mailbox "[Gmail]/All Mail" of account id "..."

So we simply seem unable to express the intention of deleting a message from a specific mailbox in AppleScript. All roads lead to Rome, or All Mail as may be the case here.


I’m not going to test this since I’ve already spent way more time on this than I should have and the hack works. But one can create a new message viewer window and select which mailboxes it displays. If one makes a viewer showing only INBOX (and not All Mail), and then gets a reference to an email via that viewer… What happens if you delete that message? Theory being that since this particular viewer doesn’t “have” All Mail, maybe it’ll correctly remove the message from the only mailbox it knows, the inbox – ultimately removing the Inbox label in isolation, which as we know is the same as archiving.

It’s good to confirm that m2 and m3 are indeed the same object. We’ve learned quite a lot about the inner workings of Mail.app, which is frustratingly opaque. The error message I got when I tried “Drafts” instead of “Trash” got me thinking that Gmail server might also have a hand in this, for example, when the message disappears and immediately reappears on “Move” action. I’ve also spent an embarrassing amount of time on this (I’ve even tried to peek into Mail.app’s SQLite database to no avail), but I’m grateful that you’ve found a good workaround for all of us to use.