bash 脚本从特定地址(pop3 帐户)删除邮件

bash script delete mails from specific address (pop3 account)

我想清理邮箱中来自特定地址的邮件

我有几千条消息,我想在 bash 脚本中执行此操作,并且 运行 时不时地(从不同的地址接收垃圾邮件,不幸的是我的 "spam filters"对他们的影响很小)

要通过命令行与邮件服务器交互,您可以使用 telnetopenssl

您可以使用以下命令连接到您的 pop 服务器(我以 gmail 为例。您必须查找您的电子邮件主机 pop3 地址和套接字。):

openssl s_client -connect pop.gmail.com:995 -quiet

由于此命令是交互式的,它会要求输入用户名、密码和一系列命令。

expect是一个可以自动与交互式命令进行交互的工具。基本语法如下: expect "somestring" action -> 如果我们监控的程序显示“somestring”,我们执行该操作。

这是一个脚本,可以删除您电子邮件地址中存在的所有邮件:

#!/usr/bin/expect

#you can modify the timeout if the script fails
set timeout 1

#our connection variables
set ip "pop.gmail.com"
set socket "995"
set user "user.name"
set pass "password"

#we set the address we want to remove mails from here. Escape special regex characters such as dots.
set target_address "mail\.example@gmail\.com"

#we launch the subprocess we want to interact with
spawn openssl s_client -connect $ip:$socket -quiet

#if connection went all right, we try to login
expect -re ".OK.*" {send "user $user\r"}
expect -re ".OK.*" {send "pass $pass\r"}

#if login went alright, we try to count the messages on the server
#you will get the following output :
#+OK NB_MSG TOTAL_SIZE
expect -re ".OK.*" {send "stat\r"}

#if the stat command went alright ...
expect -re ".OK.*" {
        #we extract the number of mail from the output of the stat command
        set mail_count [lindex [split [lindex [split $expect_out(buffer) \n] 1] " "] 1]

        #we iterate through every email...
        for {set i 1} {$i <= $mail_count} {incr i 1} {
            #we retrieve the header of the email
            send "top $i 0\r"
            
            #if the header contains "To: $target_address" (or "To: <$target_address>" or "To: Contact Name <$target_address>" ...)
            #to filter according to the sender, change the regex to "\nFrom: ..."
            expect -re "\nTo: \[^\n\]*$target_address" {
                    #we delete the email
                    send "dele $i\r"
            }
        }
}
expect default

您可能需要更改您的电子邮件帐户设置以允许使用外部程序

这里我在PHP写了一个类似的脚本,利用PHP的IMAP功能。我没有 Linux,所以无法使用 bash 脚本。然而。我认为共享 PHP-script 将为那些 运行 WINDOWS 并具有访问权限

的人提供解决方案
<?php 
echo "My showmail.php script";

// This is the format for opening the email connection:
//
//                           domain       prt foldr[.<.subfolder........>]   my@blp.com   xxxxxxxx      
// $connection = imap_open('{imap.one.com:143}Inbox.<write subfolder here>','email-name','password');
// Execution: (write this in the browsers address bar)
http://digitalageinstitute.com/showmail.php?fromdate=01%20January%202009&todate=28%20August%202018&search=@weheartit.com&email=david.svarrer@digitalageinstitute.com&password=xxxxxxx&domain=imap.one.com&folder=Inbox
//
// This line above, entered into a browsers address bar will execute this script (named showmail.php), 
// from the servers root (www.digitalageinstitute.com), and
//
// will delete emails from the mail folder "Inbox" (case sensitive) for the user david.svarrer@digitalageinstitute.com, by use of
// the IMAP domain (this is where you access emails from outside) imap.one.com and at port 143 (see this, further down)
// 
$emailaddress = $_GET["email"];
$emailpassword= $_GET["password"];
$fromdate = $_GET["fromdate"];
$todate = $_GET["todate"];
$search = $_GET["search"];
$domain = $_GET["domain"];
$folder = $_GET["folder"];
echo $emailaddress." ".$emailpassword." ".$fromdate." ".$todate." ".$search." ".$domain." ".$folder;

$connection = imap_open('{'.$domain.':143}'.$folder,$emailaddress,$emailpassword);
$ccount = imap_num_msg($connection);
$maxtoexpunge=20000;

echo "Parameters = ".$fromdate.",".$todate.",".$search.":".'ALL FROM "'.$search.'" SINCE "'.$fromdate.'" BEFORE "'.$todate.'"';

// $some   = imap_search($connection, 'ALL FROM "Twitter"');
$some   = imap_search($connection, 'ALL FROM "'.$search.'" SINCE "'.$fromdate.'" BEFORE "'.$todate.'"');
print_r ($some);
echo "<br/>Elements: ".count($some)."<br/>";
$expunge = 0;
for($msgno = 0; $msgno < count($some) ; $msgno++) {

    // echo "Fetching element ".$some[$msgno]."<br/>";
    $headers = imap_headerinfo($connection, $some[$msgno]);
    //$position = True;
    $position = strpos(" ".strtolower($headers->fromaddress), strtolower($search));
    $position2 = strpos(" ".strtolower($headers->subject), strtolower($search));
    if ($position || $position2) {
       if ($expunge<$maxtoexpunge) {
           imap_delete ($connection, $some[$msgno]);  
           echo "<br/>Deleting:".$expunge." sequence [".$msgno."]=".$some[$msgno]." ".$headers->fromaddress.", subject:".$headers->subject;
           $expunge++;
       } else {
           echo "<br/>Skipping:"." sequence [".$msgno."]=".$some[$msgno]." ".$headers->fromaddress.", subject:".$headers->subject;
       }
    }
}

// The expunge command deletes after all action has been taken. DON'T call it until very end, as it will otherwise mess up message numbers!!
imap_expunge ($connection);
echo "<br/>Expunged!!<br/>";


/* Here are the keywords to be used for the imap search order. 
toaddress - full to: line, up to 1024 characters
to - an array of objects from the To: line, with the following properties: personal, adl, mailbox, and host
fromaddress - full from: line, up to 1024 characters
from - an array of objects from the From: line, with the following properties: personal, adl, mailbox, and host
ccaddress - full cc: line, up to 1024 characters
cc - an array of objects from the Cc: line, with the following properties: personal, adl, mailbox, and host
bccaddress - full bcc: line, up to 1024 characters
bcc - an array of objects from the Bcc: line, with the following properties: personal, adl, mailbox, and host
reply_toaddress - full Reply-To: line, up to 1024 characters
reply_to - an array of objects from the Reply-To: line, with the following properties: personal, adl, mailbox, and host
senderaddress - full sender: line, up to 1024 characters
sender - an array of objects from the Sender: line, with the following properties: personal, adl, mailbox, and host
return_pathaddress - full Return-Path: line, up to 1024 characters
return_path - an array of objects from the Return-Path: line, with the following properties: personal, adl, mailbox, and host
remail -
date - The message date as found in its headers
Date - Same as date
subject - The message subject
Subject - Same as subject
in_reply_to -
message_id -
newsgroups -
followup_to -
references -
Recent - R if recent and seen, N if recent and not seen, ' ' if not recent.
Unseen - U if not seen AND not recent, ' ' if seen OR not seen and recent
Flagged - F if flagged, ' ' if not flagged
Answered - A if answered, ' ' if unanswered
Deleted - D if deleted, ' ' if not deleted
Draft - X if draft, ' ' if not draft
Msgno - The message number
MailDate -
Size - The message size
udate - mail message date in Unix time
fetchfrom - from line formatted to fit fromlength characters
fetchsubject - subject line formatted to fit subjectlength characters
*/


?> 

我一直在寻找一个 bash 脚本,但由于没有找到我自己制作的脚本,所以只需要外部程序即可 SSL/TLS 连接到服务器:

#!/bin/bash -
#===============================================================================
#
#          FILE: delete-mail.sh
# 
USAGE="./delete-mail.sh user pass [server] [port] [max_delete]"
#
#     PARAMETER: user pass - login credentials, mandatory
#                server - mail server, default: imap.1und1.de
#                port - port on mail server, default: pop3s
#                max_delete - maximum # of messages to delete, default: 1000
# 
DESCRIPTION="delete max_delete messages in given pop3 mailbox"
# 
#        AUTHOR: KayM (), kay@rrr.de
#       CREATED: 09.06.2021 18:03:58
#      REVISION:  ---
#===============================================================================

# check args
if [[ "" == "-h"* ]]; then
        printf "usage: %s\ndescr: %s\n" "$USAGE" "$DESCRIPTION" 1>&2
        exit

elif [ "$#" -lt 2 ]; then
        printf "Missing args, usage: %s\n" "$USAGE"
        exit 1
fi

# assign values
USER=""
PASS=""

SERVER="${3:-imap.1und1.de}"
PORT="${4:-pop3s}"
MAX_MESSAGE="${5:-100}"

# define actions
popserver() { socat - "OPENSSL:$SERVER:$PORT" 2>/dev/null; }

poplogin() {
        printf "USER %s\n" "$USER"
        sleep 0.5
        printf "PASS %s\n" "$PASS"
        sleep 0.5
}       

deletemsg() {
        for (( j = 1 ; j <= MAX_MESSAGE; j++ ))
        do
                printf "DELE %s\n" "$j"
                sleep 0.5
        done    
}       

popstat() { echo "STAT"; }
popquit() { echo "QUIT"; }

checkresult() {
        local line
        while read -r line
        do
                [[ "$line" == "-ERR "* ]] && MAX_MESSAGE=0
                printf "%s\n" "$line"
        done    
}

# get message count, remove newline
RES="$({ poplogin; popstat; } | popserver | tail -n 1 )"
RES="${RES//[$'\r\n']}"

if [[ "$RES" == "+OK 0 "* ]]; then
        printf "No messages to delete (%s)\n" "$RES"
        exit
elif [[ "$RES" == "+OK "* ]]; then
        : "${RES#+OK }"; NUM="${_%% *}"
        printf "%s Messages found (%s)\n" "$NUM" "$RES"
        [ "$NUM" -lt "$MAX_MESSAGE" ] && MAX_MESSAGE="$NUM"
else
        printf "Can't get number of messages: %s\n" "$RES"
        exit 1
fi

if [ "$MAX_MESSAGE" = "0" ]; then
        printf "Keep all messages\n"
        exit
fi      

# delete messages
printf "Delete %s messages ...\n" "$MAX_MESSAGE"
{ poplogin; deletemsg; popstat; popquit;} | popserver | checkresult