Página inicial da Proton

Filtro Sieve (filtros personalizados avançados)

Leitura
41 min
Categoria
Receber e ler e-mails

O Proton Mail oferece aos utilizadores várias formas de filtrar automaticamente os e-mails, atribuindo-lhes etiquetas ou organizando-os em pastas. Em geral, existem três métodos:

  1. Adicionar remetentes à Lista de endereços bloqueados e Lista de endereços permitidos de modo a que sejam sempre ou nunca colocados na pasta de spam;
  2. Criar um filtro personalizado utilizando a interface interativa do Proton Mail;
  3. [Mais avançado] Criar um filtro personalizado no Sieve.

Destes métodos, a criação de um filtro personalizado no Sieve oferece a maior versatilidade, mas também é mais complicada de utilizar. Por este motivo, consideramos o Sieve uma funcionalidade avançada para utilizadores com alguma experiência técnica. Para a maioria dos utilizadores, a interface interativa é adequada para criar os filtros personalizados de que necessita.

Índice

O que é o Sieve?

O Sieve é uma linguagem de programação utilizada para filtrar e-mails. Pode criar filtros no Sieve escrevendo regras simples. Por exemplo, “Atribuir a etiqueta verde a todas as mensagens de Kyle”. A combinação destas regras pode criar um sistema de filtragem sofisticado.

Pode escrever regras do Sieve de raiz, copiá-las de exemplos como os deste artigo ou utilizar software que facilite o processo.

Na verdade, já lhe oferecemos uma forma de criar filtros Sieve utilizando a interface interativa, que utiliza os seus dados introduzidos para gerar filtros Sieve. Outra boa forma de aprender Sieve é criando filtros através da interface interativa e editando-os no Sieve, uma vez que a própria interface interativa utiliza um subconjunto de Sieve.

Por exemplo, compare o seguinte filtro criado utilizando a interface interativa…


… com o código para o mesmo filtro visualizado no editor Sieve:

Este artigo irá apresentar-lhe o Sieve e explicar como escrever os seus próprios filtros Sieve. Se necessitar de mais informações sobre como utilizar o Sieve, existem inúmeros outros tutoriais online que podem ajudar. Se tiver dúvidas sobre o Sieve no Proton Mail que não sejam respondidas nesta página, pode sempre contactar a equipa de apoio ao cliente aqui.

Primeiros passos

Para começar a criar filtros Sieve, inicie sessão em mail.proton.me(nova janela), vá a Definições → Todas as definições → Proton Mail → Filtros → Adicionar filtro sieve.

Um script Sieve é composto por uma lista de comandos. Na maioria dos scripts, começa com um comando require. O comando require carrega uma extensão que fornece uma determinada funcionalidade. Por exemplo, para atribuir uma etiqueta ou colocar uma mensagem numa pasta, necessitamos do comando fileinto.

Para carregar este comando, escrevemos simplesmente:

require "fileinto";

Para carregar múltiplas extensões, pode utilizar uma lista:

require ["fileinto", "imap4flags"];

Neste caso, o imap4flags carrega uma extensão que lhe permite marcar o correio como lido. Após o comando require, irá frequentemente realizar alguns testes na mensagem recebida. Isto é feito combinando o if com outro comando, como address ou header.

Por fim, se os testes forem bem-sucedidos, pode aplicar uma acção a uma mensagem. Por exemplo, suponha que queremos colocar todos os e-mails de um remetente específico na mesma pasta e marcar o correio recebido como lido. Isto poderia ser escrito como:

require ["fileinto", "imap4flags"];
# I don't really like Spott
if address :is "from" "Spott.Tenerman@northpark.example.com"
{ 
    addflag "\\Seen";
    fileinto "enemies";
}

Note que o carácter # indica um comentário e não é interpretado como parte do script Sieve. Além disso, a pasta ou a etiqueta que definir (neste caso, enemies) tem de existir no seu ambiente: pode aprender a criar pastas e etiquetas aqui. Depois de introduzir este filtro, clique no botão GUARDAR. O seu filtro será agora executado para todos os e-mails recebidos.

Claro que pode querer colocar e-mails de múltiplos remetentes na mesma pasta. Neste caso, pode passar uma lista de strings para o comando address (uma string(nova janela) é uma série de caracteres, neste caso um endereço de e-mail):

require ["fileinto", "imap4flags"];
# I don't really like Spott and Kyyyhel
if address :is "from" ["Spott.Tenerman@northpark.example.com", "Kyhel.Broski@northpark.example.com"]
{ 
    addflag "\\Seen";
    fileinto "enemies";
}

Note que sempre que pode passar uma string para uma condição de teste, normalmente também é possível passar uma lista. Irá então tentar encontrar uma correspondência testando qualquer uma das strings na lista. Isto não se aplica a comandos como fileinto, addflag, etc.

Mas o Sieve é mais poderoso do que apenas reordenar a sua caixa de correio. Também lhe permite rejeitar e-mails com uma mensagem de resposta:

require "reject";
# Reject mails that spell my name wrong
if header :contains "subject" "Kyhel"
{
    reject "My name is not Kyhel";
}

Utilizar testes

Combinar testes no Sieve

Como lhe mostrámos na secção Primeiros passos, pode realizar testes utilizando o comando if em mensagens recebidas para determinar se um e-mail deve ser afetado por um comando require.

Além do comando if, existem outros comandos de teste que lhe permitem estruturar o seu script de forma simples.

Else

O comando else permite-lhe fazer algo quando o comando if não executou as suas acções. Um exemplo disto é:

require ["fileinto"];
# If the subject contains something incomprehensible, then put the mail into the kenny folder
if header :contains "subject" "mmph mmph"
{
    fileinto "Kenny";
} else { 
    fileinto "Understandable";
}

Aqui, o e-mail será movido para a pasta Kenny se o assunto for exatamente mmph mmph. No outro caso (ou seja, quando o assunto não é exatamente mmph mmph), o e-mail será movido para a pasta Understandable.

Elsif

O elsif é a contração de else if. Tal como o comando else, será executado se a condição if for incorreta, mas apenas se a condição elsif for correta. Se o elsif não for correto, o bloco elsif ou else seguinte será executado.

require ["fileinto", "imap4flags"];
# If the subject contains something incomprehensible, then put the mail into the kenny folder
if header :contains "subject" "mmph mmph"
{
    fileinto "Kenny";
# Kyhel sends me only speeches
} elsif address :is "from" "Kyhel.Broski@northpark.example.com" { 
    fileinto "Speeches";
} else { 
# otherwise the mail is important, so add a star.
    addflag "\\Flagged";
}

Note que apenas um dos blocos if, elsif ou else será executado numa única execução.

Anyof

Por vezes, precisa de executar um comando quando um de vários testes é bem-sucedido. Para isso, pode usar o comando anyof. Isto é feito escrevendo anyof seguido de um parêntese ‘(’, as instruções que pretende testar separadas por vírgulas e um parêntese de fecho ‘)’.

require ["fileinto", "imap4flags"];
# Kenny either sends from kenny@northpark.example.com or puts "mmph mmph" in the subject.
   if anyof(address :is "from" "kenny@northpark.example.com", header :contains "subject" "mmph mmph")
{
    fileinto "Kenny";
}

Este script colocará as mensagens que provêm de kenny@northpark.example.com ou que contêm mmph mmph na linha de assunto na pasta Kenny.

Allof

Também existe a contrapartida do anyof: o allof. Isto permite-lhe executar um comando apenas quando todas as condições indicadas correspondem:

require ["fileinto", "imap4flags"];
# Kenny always sends me mails with mmph mmph
if allof(address :is "from" "Kenny@northpark.example.com", header :contains "subject" "mmph mmph")
{
    fileinto "Kenny";
}


Este script colocará as mensagens que provêm de kenny@northpark.example.com e contêm mmph mmph na linha de assunto na pasta Kenny.

Not

Por último, por vezes precisa de aplicar um comando se algo não corresponder. Adicionar not antes da instrução garantirá que isso aconteça:

require ["fileinto", "imap4flags"];
# If a subject line does not contain real guitar put it into the young people folder
if not header :contains "subject" "real guitar"
{
    fileinto "Young people";
}

O que é equivalente a:

require ["fileinto", "imap4flags"];
# The else part will be evaluated if the condition is not true
if header :contains "subject" "real guitar"
{
    # do nothing
} else {
    fileinto "Young people";
}

Isto coloca todos os e-mails que não contêm real guitar na linha de assunto na pasta Young people.

Como é óbvio, é possível combinar todos estes testes. Por exemplo, pode querer marcar um e-mail com estrela se este não for do Kenny e também não contiver mmph mmph no assunto:

require ["fileinto", "imap4flags"];
if not anyof (    header :contains "subject" "mmph mmph", 
    address :is "from" "Kyhel.Broski@northpark.example.com" ) { 
    addflag "\\Flagged";
}

Realizar testes em cabeçalhos

Usando o comando address, pode realizar testes em cabeçalhos de endereço, tais como os cabeçalhos from, to e sender. Pode extrair diferentes partes do endereço de e-mail usando um dos seguintes sinalizadores:

  • :localpart — a parte antes do símbolo de arroba (@)
  • :domain — a parte após o símbolo de arroba (@)
  • :all — o endereço completo

O seguinte snippet explica a utilização deste comando:

require ["fileinto", "imap4flags"];
# Northpark people are made of paper, springfield are mostly yellow
if address :domain "from" "northpark.example.com"
{
    fileinto "PaperPeople";
} elsif address :domain "from" "springfield.example.com"{
    fileinto "YellowPeople";
}
if address :localpart "from" "chef"
{
    addflag "\\Flagged";
}

Em resumo, este script colocará tudo o que for enviado do domínio northpark.example.com em PaperPeople e de springfield.example.com em YellowPeople.

Além disso, independentemente do domínio de onde um e-mail é enviado, se a parte antes de @ for igual a chef (por exemplo, chef@example.com), a mensagem será marcada. Outra utilização interessante é guardar automaticamente tudo o que for enviado para um endereço numa pasta:

require ["fileinto", "imap4flags"];
# Put support mail in a separate organized folder
if address :localpart "to" "support"
{
    fileinto "Support";
}

Avançado

O comando envelope permite-lhe realizar mais testes. Em geral, o teste address apenas obtém o valor a partir do cabeçalho. No entanto, na sessão SMTP, é possível especificar um endereço from diferente daquele que consta no cabeçalho.

Na interface de cabeçalho do Proton Mail, o envelope-from é igual ao cabeçalho return-path e o envelope-to é igual ao cabeçalho x-original-to.

Utilizando o comando envelope, pode obter os endereços to: e from: reais a partir do envelope. Tenha em atenção que não existem outros campos além destes dois, pelo que o sender não existe neste comando. Tenha também em atenção que o envelope está numa extensão e, por isso, requer que utilize o comando require para esta extensão primeiro.

require ["fileinto", "imap4flags", "envelope"];
# Northpark people are made of paper, springfield are mostly purple
if envelope :domain "from" "northpark.example.com"
{
    fileinto "PaperPeople";
} elsif envelope :domain "from" "springfield.example.com"{
    fileinto "PurplePeople";
}
if envelope :localpart "from" "chef"
{
    addflag "\\Flagged";
}

Usar comparadores para avaliar dois valores

Quando um teste avalia dois valores, é possível especificar como esta comparação é feita utilizando diferentes sinalizadores chamados comparadores. Anteriormente, já usámos dois comparadores: :is e :contains, que verificam se a cadeia de caracteres fornecida é exatamente igual ao valor específico, e se o valor específico contém a cadeia de caracteres fornecida, como no teste seguinte.

require ["fileinto", "imap4flags"];
if not anyof (
    header :contains "subject" "mmph mmph", # the subject contains mmph mmph 
    address :is "from" "Kyhel.Broski@northpark.example.com" # the recipient is exactly Kyhel.Broski@northpark.example.com
) { 
    addflag "\\Flagged";
}

O comparador :matches também pode ser utilizado para definir um formato mais específico. Irá comparar ambos os valores do início ao fim, tal como o comparador :is. No entanto, no caso de :matches, o valor que definiu pode conter os valores ? e *. O ponto de interrogação corresponderá a um carácter, e a estrela (chamada de carácter universal) corresponderá a zero ou mais caracteres.

Com este formato, pode criar este teste:

require ["fileinto", "imap4flags"];
if header :matches "subject" "mmph*" { 
    addflag "\\Flagged";
}

Neste exemplo, o teste será bem-sucedido se o assunto da mensagem começar com mmph e, em seguida, contiver qualquer carácter ou caracteres a seguir. Por outras palavras, o e-mail será marcado quando o assunto começar com ‘mmph’. Tanto ‘mmph mmph’ como ‘mmph mmph Hello’ irão corresponder; ‘Hello mmph’ e ‘Springfield sales’ não.

A estrela também pode ser usada no meio do valor e várias vezes, da seguinte forma:

require ["fileinto", "imap4flags"];
if header :matches "subject" "mmph *mmph *mmph" { 
    addflag "\\Flagged";
}

Este teste corresponderá se o assunto começar com ‘mmph ’ (com um espaço), contiver outro ‘mmph ’ (com um espaço) e terminar com ‘mmph’ (sem um espaço). Os assuntos correspondentes são ‘mmph mmph mmph’, ‘mmph mmph mmphmmph’ ou ‘mmph is mmph and mmph’.

Este comparador :matches pode ser muito útil na comparação de endereços. Como deve saber, o Proton Mail tem vários domínios: protonmail.com e proton.me. Se quiser verificar se uma mensagem provém de um utilizador do Proton Mail, pode usar este script:

require ["fileinto", "imap4flags"];
# Put support mail in a separate organized folder
if address :domain :matches "from" "protonmail.*"
{
    fileinto "Internal";
}

Se por algum motivo precisar de fazer a correspondência exata do carácter * ou ?, pode protegê-los adicionando \\ antes: \\* corresponderá a uma estrela e \\? corresponderá a um ponto de interrogação.

Note que também suportamos a extensão regex, que também define o comparador :regex. Este comparador é uma versão mais precisa do :matches, mas é muito complexo. Para mais informações, leia a documentação oficial(nova janela).

Em alguns casos (como verá no seguimento deste artigo), poderá querer comparar valores numéricos. O pacote relational foi concebido para esta utilização. Este pacote define o comparador :value, que é seguido pelo tipo de comparação.

Permite-lhe verificar se um valor é maior do que (sendo o tipo de comparação “gt”), maior ou igual a (“ge”), igual a (“eq”), menor ou igual a (“le”) ou menor do que (“lt”) o valor fornecido.

Ao comparar valores numéricos, o pacote comparator-i;ascii-numeric também é muito útil. Ele indica ao interpretador de scripts que o conteúdo da cadeia de caracteres é um número, e não uma cadeia de caracteres normal. Pode ser utilizado adicionando ao teste :comparator “i;ascii-numeric”.

Com todas estas informações, podemos criar o seguinte script:

require ["fileinto", "relational", "comparator-i;ascii-numeric"];  
if header :value "ge" :comparator "i;ascii-numeric" "subject" "2"   
{    
 fileinto "Dummy example";
}

Este teste moverá a mensagem para a pasta Dummy example se o assunto for maior ou igual a 2. Se o assunto não for um número, mas sim um texto, o teste falhará. Como tal, este exemplo parece muito simples, mas destina-se a ser utilizado em combinação com outras extensões, como date, que definiremos mais à frente neste artigo.

Comparação usando o contexto no Sieve

Também pode aceder a informações relacionadas com a sua conta e o contexto do Proton Mail em geral usando extensões. Por exemplo, pode verificar se o endereço do remetente está na sua lista de contactos.

Aceder à sua lista de contactos

Pode aceder à sua lista de contactos utilizando a extensão extlists. Em combinação com os testes de cabeçalho, pode verificar se um contacto está na sua lista de contactos.

require ["fileinto", "extlists"];  
# Checks that the sender is in your personal address book
if header :list "from" ":addrbook:personal?label=Family"   
{    
 fileinto "Known"; 
}

Este teste marcará uma mensagem com a etiqueta Known se o remetente constar na lista :addrbook:personal?label=Family. A lista pode ser dividida em duas partes. Primeiro, :addrbook:personal significa que o endereço está no seu livro de endereços pessoal. Segundo, label=Family restringe ainda mais a lista, especificando que, além de estar no seu livro de endereços, o contacto também deve pertencer ao grupo de contactos Family. Se precisar, pode alterar esta etiqueta para outro grupo de contactos. Pode utilizar :addrbook:personal?label=Work se quiser, caso em que o teste seria bem-sucedido apenas se o remetente estivesse no seu livro de endereços e no grupo de contactos Work.

De forma mais geral, uma lista respeita o Tag URI Scheme(nova janela), e pode adicionar parâmetros adicionais para restringir os seus filtros. Depois, pode utilizar esta lista da seguinte forma:

require ["fileinto", "extlists"];  
# replace :your:list:here by the list you want to use
if header :list "from" ":your:list:here"
{    
 # some actions... 
}

Disponibilizámos quatro listas diferentes:

  • :addrbook:personal¹ verifica se um endereço está na sua lista de contactos. A lista aceita o parâmetro label que corresponde a um grupo de contactos específico. Este parâmetro pode ser declinado em quatro subversões:
    • :addrbook:personal?label=something corresponderá a um contacto que está no grupo de contactos “something”;
    • :addrbook:personal?label.starts-with=something corresponderá a um contacto que pertence a, pelo menos, um grupo que começa com “something”;
    • :addrbook:personal?label.ends-with=something corresponderá a um contacto que pertence a, pelo menos, um grupo que termina com “something”;
    • :addrbook:personal?label.contains=something corresponderá a um contacto que pertence a, pelo menos, um grupo que contém “something”.

Também pode aceder a informações criptográficas relativas ao e-mail correspondente:

  • :addrbook:personal?keypinning=true corresponderá a um contacto que tem uma chave de confiança. Alterar de true para false corresponderá a um contacto que não tem uma chave de confiança;
  • :addrbook:personal?encryption=true corresponderá a um contacto para o qual a encriptação está ativada. Alterar de true para false corresponderá a um contacto para o qual a encriptação não está configurada ou está desativada;
  • :addrbook:personal?signing=true irá corresponder a um contacto para o qual a assinatura está ativada. Alterar true para false irá corresponder a um contacto para o qual a assinatura está desativada.
  • :addrbook:myself¹ corresponde a cada endereço que lhe pertence;
  • :addrbook:organization corresponde a todos os endereços que pertencem a alguém na organização de que é membro;
  • :incomingdefaults:inbox verifica se o endereço está na sua Lista de endereços permitidos;
  • :incomingdefaults:spam verifica se o endereço está na sua Lista de endereços bloqueados.

Combinado com a extensão de variáveis (descrita no parágrafo seguinte), as variáveis de correspondência serão alteradas. A variável de correspondência ${0} conterá sempre o último endereço de e-mail contido na lista especificada. Se a lista tiver sido marcada com a nota 1, a variável de correspondência ${1} conterá o nome a apresentar.

Por exemplo, com as listas abaixo, pode criar um filtro que eliminará quaisquer e-mails recebidos de qualquer pessoa que não pertença à sua família ou que não esteja na sua lista branca:

require "extlists";  
# checks that the sender is not in the contact group Family, whilelisted or yourself
if not anyof(
    header :list "from" ":addrbook:personal?label=Family", 
    header :list "from" ":incomingdefaults:inbox",
    header :list "from" ":addrbook:myself"
) {    
  discard; # permanently delete the email
}

Se essa condição for cumprida, a ação discard será executada. Esta ação elimina o e-mail imediata e permanentemente . Também poderia simplesmente movê-lo para a pasta do Lixo utilizando uma ação fileinto em vez de um descarte: fileinto “trash”;.

Criar variáveis

Outra ferramenta útil ao gerir o contexto é a definição de variável. Uma variável é uma localização de armazenamento temporária na qual pode colocar texto e etiquetá-lo com um nome. Mais tarde, poderá reutilizar este conteúdo chamando-o pelo seu nome. Por exemplo, poderia ter o seguinte script:

require ["reject", "variables"];
# First check who is the sender
if allof(
    address :is "from" "Kenny@northpark.example.com", 
    header :contains "subject" "mmph mmph"
) {
    # It's from Kenny!
    # Create the variable message containing 'mmph mmph'
    set "message" "mmph mmph";
} else {
    # Create the variable message containing 'Sorry, I don't want emails today!'
    set "message" "Sorry, I don't want emails today!";
}
# Then, reject the message
reject "${message}";

O objetivo deste script é rejeitar um e-mail com uma mensagem personalizada. Se o e-mail original for de kenny e o seu assunto for ‘mmph mmph’, a variável ‘message’ é criada, contendo mmph mmph. No outro caso, a mensagem será preenchida com ‘Sorry, I don’t want emails today!’. Depois, no último passo, reutilizamos esta variável no comando reject.

O Sieve não define variáveis nativamente, pelo que as mesmas são definidas na extensão variables, que tem de ser requerida no início do seu script. Existem duas formas de definir uma variável.

  • Criação explícita de uma variável:

A ação set é fornecida para criar uma variável.

require "variables";
# Create a variable called "labelname" and containing the string "Work".
set "labelname" "Work";

A primeira string é o nome da sua variável e a segunda é o valor da sua variável. Assim, o exemplo anterior cria uma variável chamada labelname e que contém Work.

Assim que uma variável estiver definida, pode chamá-la adicionando o seguinte formato numa string: ${name}, onde name é o nome da sua variável. Quando executada, será substituída pelo valor da variável. (Se não tiver definido a variável, esta será substituída por uma string vazia.) Assim, no seguinte script:

require "variables";
require "fileinto";
# Create a variable called "labelname" and containing the string "Work".
set "labelname" "Work";
# Move the email in "${foldername}/${labelname}" which becomes after variable resolution "/Work";
fileinto "${foldername}/${labelname}";

O seu e-mail será marcado com a etiqueta /Work. Como já definimos a variável labelname, esta é substituída por Work. No entanto, foldername não está definida, por isso é simplesmente removida.

  • Atribuição implícita de uma variável:

O caso de utilização mais interessante das variáveis é quando se utiliza um teste :matches. Vejamos o seguinte exemplo, onde o remetente do e-mail é test@proton.me:

require "variables";
require "fileinto";
# do a matches test 
if header :matches "from" "*@*" {
    # The first * matches "test", the second "protonmail".  
    # Thus, the first matching variable contains "test"
    fileinto "${1}";
}

Quando utilizado com a extensão de variáveis, o resultado de uma operação match será armazenado nas variáveis. Várias variáveis serão definidas com um nome numérico. Primeiro, a variável 0 conterá a correspondência completa (no nosso exemplo, será o endereço completo: test@proton.me). Em seguida, o primeiro grupo de correspondência será atribuído à variável 1 (no nosso exemplo, será test), o segundo grupo de correspondência será atribuído à segunda variável (proton.me) e assim sucessivamente até ao último grupo de correspondência.

No nosso exemplo, o comando fileinto é executado. A localização é definida para ${1}, que é reconhecida como uma variável e, portanto, substituída pelo seu valor, conforme calculado acima: test.

Note que também é possível atribuir variáveis num teste :regex, utilizando grupos de correspondência de expressões regulares.

Transformar variáveis

Uma excelente possibilidade é a transformação de variáveis. Para isso, a palavra-chave set pode ser utilizada com uma combinação de flags que podem ser usadas para alterar o valor antes de o atribuir à variável.

  • :lower alterará o valor de uma variável para minúsculas;
  • :upper alterará o valor de uma variável para maiúsculas;
  • :lowerfirst alterará a primeira letra do valor da variável para minúsculas;
  • :upperfirst alterará a primeira letra do valor da variável para maiúsculas;
  • :quotewildcard colocará entre aspas qualquer carácter universal contido na string, para que possa ser utilizado literalmente numa instrução match;
  • :length devolverá o comprimento do valor.

Note que também pode reutilizar uma variável definida noutra ação set. Vamos melhorar os nossos exemplos anteriores:

require "variables";
require "fileinto";
# Set labelname to WORK, and modify it to lowercase with the first letter in upper case 
set :lower :upperfirst "labelname" "WORK";
set :lower :upperfirst "foldername" "geneva";
# Create a variable that is a combination of foldername and labelname
set "location" "${foldername}/${labelname}";
fileinto "${location}";

Passo a passo, o filtro criará três variáveis. O primeiro comando set criará a variável labelname. O conteúdo da variável é Work. De facto, o valor original WORK é transformado utilizando as flags :lower e :upperfirst, alterando a caixa para work e depois para Work.

O segundo comando set criará uma segunda variável chamada foldername, que conterá a string Geneva. De facto, foram utilizadas as flags :lower e :upperfirst.

Finalmente, a variável location é criada. O valor “${foldername}/${labelname}” contém duas variáveis: foldername and labelname. Assim, o intérprete Sieve substituirá estas variáveis pelos seus valores: Work e Geneva.

Finalmente, a variável location é utilizada como argumento para o comando fileinto. Assim, o e-mail será movido para a pasta cujo nome é o valor da variável location: Work/Geneva.

Os comparadores também podem ser aplicados a variáveis de correspondência:

require "variables";
require "fileinto";
if address :all :matches "from" "*@*" {
    set :lower :upperfirst "fileintovar" "${1}";
    fileinto "${fileintovar}";
}

Aqui, se o remetente do e-mail for test@proton.me, este será marcado com a etiqueta Test.

Outra forma de alterar o valor de uma variável é utilizar a extensão vnd.proton.eval. Esta extensão define a nova flag :eval, que lhe permitirá fazer alguns cálculos simples:

require "variables";
require "fileinto";
require "vnd.proton.eval";
# do a match test on the sender address
if header :matches "from" "*" {
    # create a variable called length, containing the length of the first     
    # matching variable
    set :length "length" "${1}"; 
    # Create a variable called fileintovar containing the result of the expression written below
    set :eval "fileintovar" "${length} * 25 - 1 / 8+3";
    fileinto "${fileintovar}";
}

Neste exemplo, e considerando ainda que o e-mail chega de test@proton.me, o e-mail será marcado com o valor 478. De facto, o comprimento da primeira variável de correspondência é 19, e o resultado de 19 * 25 – 1 / 8 + 3 é arredondado para 478.

Isto pode parecer inútil ao início, mas esta extensão faz mais sentido quando combinada com outras operações.

Comparação com outros campos no Sieve

A correspondência em cabeçalhos específicos também é possível. Por exemplo, para colocar todas as mensagens enviadas para listas (muitas vezes tratam-se de mensagens de marketing ou boletins informativos), pode fazer o seguinte:

require "fileinto";
# Filter all lists into the same folder
if exists "list-unsubscribe"
{
    fileinto "advertisements";
}

Para ordenar os e-mails das redes sociais para a sua própria pasta, poderá escrever:

require "fileinto";
# Filter all lists into the same folder
if anyof(exists "x-facebook", exists "x-linkedin-id") {
    fileinto "social";
} elsif exists "list-unsubscribe"
{
    fileinto "advertisements";
}

Note que utilizamos:

anyof(exists "x-facebook", exists "x-linkedin-id")

em vez de:

exists ["x-facebook", "x-linkedin-id"]

Visto que este último verifica se tanto o x-facebook como o x-linkedin-id foram definidos.

Para ver efetivamente que valor contém um cabeçalho, pode utilizar o teste header:

require "fileinto";
# Put all mails that have been sent without TLS/SSL into the same folder
if header :is "x-pm-transfer-encryption" "none" {
    fileinto "unencrypted";
}

Além da operação :is, que faz uma correspondência exata, o comando header também suporta :matches, que faz a correspondência utilizando caracteres universais (por exemplo, “*@*.com” corresponderá a qualquer endereço de e-mail que termine em ponto com), e o comando :contains, que verifica se o cabeçalho contém uma determinada string.

Para criar filtros Sieve, pode ser útil obter os cabeçalhos de um e-mail. Para o fazer na interface web do Proton Mail, aceda a Mais () → Ver cabeçalhos. Uma nova janela abrir-se-á com todos os cabeçalhos do e-mail.

Filtrar por tamanho de mensagem no Sieve

É possível tratar e-mails grandes de forma diferente de e-mails pequenos. Por exemplo, pode querer marcar e-mails grandes, de modo a poder eliminá-los para poupar espaço na caixa de correio. Isto pode ser feito da seguinte forma:

require ["imap4flags"];
# Flag emails that probably have large attachments (> 2 MiB)
if size :over 2M # you can also use 2097152 if you want, they are synonymous
{
    addflag "\\Flagged";
}
# Automatically mark as read really small messages. They can't have much content anyway...
if size :under 1000
{
    addflag "\\Seen";
}

Como pode ver, estão disponíveis unidades se quiser especificar tamanhos grandes, adicionando a letra correspondente à unidade pretendida logo após o número. Estão disponíveis três unidades: K para um kibiocteto (ou 1024 bytes), M para um mebiocteto (ou 1 048 576 bytes) e G para um gibiocteto (ou 1 073 741 824 bytes).

Tenha em atenção que “over” neste caso significa maior do que, e “under” significa menor do que. Isto significa que, se uma mensagem tiver um tamanho de exatamente 1000 bytes, então nem

size :under 1000

nem

size :over 1000

irá corresponder.

Note que os filtros do Sieve não têm acesso ao conteúdo real e apenas mostram o tamanho encriptado.

Executar acções avançadas em mensagens

Pode executar reações diferentes a uma mensagem no Sieve. Já apresentámos as acções fileinto, addflag, discard e reject nas secções anteriores. Aqui iremos apresentar acções mais avançadas.

Mensagens de férias e testes de data

Pode replicar a funcionalidade de resposta automática no Sieve utilizando o comando vacation. De facto, a funcionalidade de resposta automática nas suas Definições depende do Sieve para funcionar. Mas ao utilizar as opções de férias dentro de um script, tem muito mais possibilidades de personalizar as suas respostas automáticas. Por exemplo, pode criar mensagens específicas dependendo das condições. Nota: Tal como acontece com a funcionalidade de resposta automática nas Definições, a acção vacation apenas está disponível em planos pagos.

O comando vacation envia uma resposta de férias a qualquer pessoa que tente contactá-lo. É frequentemente associado aos testes currentdate ou date para enviar respostas num determinado período de tempo.

Suponha que vou de férias de 14 de julho de 2017 a 14 de agosto de 2017, no fuso horário do Colorado. Posso utilizar o seguinte código do Sieve para definir um atendedor automático:

require ["date", "vacation", "relational"];
if allof(currentdate :zone "US/Mountain" :value "ge" "date" "2017-07-14",
 currentdate :zone "US/Mountain" :value "le" "date" "2017-08-14")
{
    vacation "Queue you guys, I'm going on vacation.";
}

Um dos argumentos opcionais para um comando vacation são os argumentos :handle e :days. Por predefinição, o Sieve não irá responder várias vezes ao mesmo remetente num número específico de dias designado por timeout. Isto evita que envie inadvertidamente inúmeros e-mails automáticos.

Para controlar o timeout, pode utilizar o parâmetro :days. O argumento :days é utilizado para especificar o período em que os endereços são mantidos e não recebem resposta, e é sempre especificado em dias. Por vezes, tem vários comandos vacation no seu script do Sieve, e precisa de garantir que cada um deles envia uma resposta pelo menos uma vez (se a regra corresponder). Nesse caso, a opção :handle pode ser utilizada. O argumento para :handle é uma cadeia de caracteres que identifica o tipo de resposta que está a ser enviada.

Para ver como isto funciona, suponha que é professor. Os professores recebem frequentemente trabalhos escolares por e-mail. É útil organizá-los na sua própria pasta. Além disso, pode rejeitar quaisquer entregas que cheguem após o prazo limite.

Num caso como este, poderá querer utilizar o identificador para garantir que as respostas são enviadas quando necessário:

require ["date", "vacation", "reject", "fileinto", "relational"];
if header :contains "subject" "Homework assignment 1"
{
    # remind people not to forget the attachments
    if size :under 5000
    {
        vacation :handle "Homework assignment 1 - missing attachment" "Your message size is really low. Please make sure you didn't forget to add the homework as an attachment.";
    }
   
    # check if the student made the deadline
    if  currentdate :zone "US/Mountain" :value "le" "date" "2017-06-12"
    {
        fileinto "Homework Assignment 1";
    } else {
        reject "Too late, you missed the deadline.";
    }
}
if header :contains "subject" "Homework assignment 2"
{
    # remind people not to forget the attachments
    if size :under 5000
    {
        vacation :handle "Homework assignment 2 - missing attachment" "Your message size is really low. Please make sure you didn't forget to add the homework as an attachment.";
    }
   
    # check if the student made the deadline
    if  currentdate :zone "US/Mountain" :value "le" "date" "2017-06-12"
    {
        fileinto "Homework Assignment 2";
    } else {
        reject "Too late, you missed the deadline.";
    }
}

Aqui estão todos os argumentos permitidos para a resposta de férias, listados na ordem em que devem ser transmitidos:

  • :days é o número de dias que o atendedor automático deve evitar enviar uma resposta ao mesmo remetente após enviar uma mensagem de férias
  • :subject é um prefixo (por predefinição, auto) que o atendedor automático deve utilizar para responder ao remetente. Por exemplo, “Trabalho Escolar 2” receberá uma resposta com “late: Trabalho Escolar 2” se :subject “late” for transmitido.
  • :mime indica que a primeira linha de resposta utiliza um formato específico. Isto permite ao remetente responder com mensagens HTML. Por exemplo, para escrever uma resposta em HTML, transmita o argumento :mime e escreva na primeira linha da resposta Content-Type : text/html.
  • :handle é uma cadeia de caracteres que identifica o tipo de resposta que está a ser enviada.

Tenha em atenção que o parâmetro :zone em currentdate é um parâmetro opcional e irá utilizar a hora local do servidor (Genebra, Suíça, no caso do Proton Mail) se não estiver definido.

O parâmetro zone aceita desvios de fuso horário, que são cadeias de caracteres no formato “+0100” que significa UTC+1, e fusos horários reais na base de dados da ICANN (ver https://en.wikipedia.org/wiki/List_of_tz_database_time_zones(nova janela)). A última opção é frequentemente mais útil (apesar de não ser padrão do Sieve), pois também codifica a hora de verão de cada fuso horário.

Pode comparar datas utilizando o parâmetro normal :is/ :contains/ :matches. Assim, por exemplo, o seguinte comando do Sieve corresponde a qualquer data em julho de 2017:

currentdate :zone "US/Mountain" :matches "date" "2017-07-??"

Mas, na maioria dos casos, o parâmetro :value é muito mais útil.

O último parâmetro que precisa de transmitir é o formato. O formato também codifica qual a parte da data que pretende comparar. No exemplo fornecido, utilizámos o formato de data. Todos os formatos suportados são:

  • year, o ano codificado no formato “0000” a “9999”
  • month, o mês codificado como “01” a “12”
  • day, o dia codificado como “01” a “31”
  • date, codificado como yyyy-mm-dd
  • hour, a hora codificada como “00” a “23”
  • minute, o minuto codificado como “00” a “59”
  • second, o segundo codificado como “00” a “60” (60 é um segundo intercalar(nova janela), que apenas ocorre às 23:59:60 quando os cientistas o consideram necessário)
  • time, a hora como hh:mm:ss
  • iso8601, a data e a hora de acordo com a norma ISO8601, por exemplo: 2005-08-15T15:52:01+00:00
  • std11, a data e a hora de acordo com a norma RFC2822, por exemplo: Mon, 15 Aug 2005 15:52:01 +0000
  • zone, o desvio de fuso horário no formato +/-zzzz, por exemplo, +0000 ou -1200
  • julian, o número de dias desde 17 de novembro de 1858 UTC
  • weekday, o dia da semana começando no domingo como 0 até ao sábado como 6

Por último, também é possível obter a data de um cabeçalho em vez de utilizar o currentdate. Este comando de data funciona da mesma forma que o currentdate, exceto que requer uma cadeia de caracteres adicional antes da cadeia de formato: o nome do cabeçalho. Por exemplo:

date :zone "US/Mountain" :matches "received" "date" "2017-07-??"

Tenha em atenção que os cabeçalhos não são necessariamente precisos: um remetente pode alterá-los à vontade e, portanto, não são fiáveis.

Considerações:

  1. O atendedor automático não responde a mensagens geradas automaticamente, tais como listas de correio, e-mails enviados por outro atendedor automático ou mensagens enviadas por um endereço de noreply.
  2. O atendedor automático não enviará mensagens várias vezes para o mesmo endereço de e-mail, exceto quando o comando vacation tiver um :handle diferente.

Gerir a expiração

Uma funcionalidade única do Proton Mail é a capacidade de definir um tempo de expiração para mensagens enviadas, momento no qual a mensagem será eliminada da caixa de correio do destinatário.

Também pode utilizar esta funcionalidade para gerir as suas mensagens recebidas, adicionando um tempo de expiração:

require "vnd.proton.expire"; 
# permanently delete all incoming and outgoing emails after 10 days
expire "day" "10";

O script acima irá eliminar qualquer e-mail recebido após 10 dias. Este é um pouco extremo, uma vez que se aplica a todos os e-mails. Em vez disso, deverá provavelmente utilizar uma condição para aplicar o script apenas a um conjunto específico de e-mails. Por exemplo, poderia expirar qualquer mensagem de alguém que não esteja nos seus contactos:

require ["extlists", "vnd.proton.expire"];
# permanently delete after 10 days any email not from me or from someone in my address book.
if not anyof(
    header :list "from" ":addrbook:personal",
    header :list "from" ":addrbook:myself"
) {
 expire "day" "10";
}

Nota: Se o tempo de expiração especificado exceder 730 dias, será automaticamente limitado a 730 dias.

Limitações do Sieve

Existem várias limitações do Sieve que deve ter em conta.

  • As mensagens enviadas não podem ser movidas manualmente ou por filtro para a Caixa de entrada/Rascunho. Ficarão sempre na pasta Enviados e na pasta/etiquetas aplicadas pelo utilizador ou filtro.
  • As mensagens recebidas não podem ser movidas manualmente ou por filtro para Rascunho/Enviados.
  • Os rascunhos não podem ser movidos manualmente ou por filtro para a Caixa de entrada/Enviados.
  • Para mensagens em Spam — ou mensagens arquivadas em spam durante o processamento — não enviamos mensagens de resposta automática/férias. Se precisar de uma funcionalidade deste género, considere adicionar uma pasta personalizada — por exemplo, mySpam — e desativar as notificações para a mesma.
  • Limitações de mensagens de resposta automática/férias

Nota sobre o suporte de expressões regulares

A implementação do Sieve da Proton segue a norma de filtragem de e-mail do Sieve, que inclui apenas um suporte mínimo para expressões regulares. Algumas sintaxes abreviadas comuns de expressões regulares, tais como \b (limite de palavra), \w (caractere de palavra), \W (caractere que não é de palavra) e \d (dígito), não são suportadas no Sieve. Como resultado, a utilização destes caracteres abreviados nos filtros pode fazer com que falhem silenciosamente. Esta limitação deve-se à própria norma do Sieve, que prioriza a simplicidade e a compatibilidade entre plataformas. Para mais detalhes, consulte o Rascunho de RFC de Expressões Regulares do Sieve.

Lista de acções e testes suportados

Pacotes

O Sieve suporta as seguintes extensões. Pode consultar a documentação oficial para obter mais informações.

Data

  • Utilização: date
  • Descrição: (nova janela)Fornece uma forma de verificar as informações de data.
  • Documentação: https://tools.ietf.org/html/rfc5260(nova janela)
  • Implementação: O comparador predefinido é i;ascii-numeric e não i;ascii-casemap. De facto, a data não é útil com o comparador casemap.
  • Consulte: Mensagens de férias e testes de data

Envelope

FileInto

  • Utilização: fileinto
  • Descrição: Aplica uma etiqueta a uma mensagem ou move-a para uma pasta.
  • Documentação: https://tools.ietf.org/html/rfc5228#section-4.1(nova janela)
  • Implementação: As barras indicam o caminho completo das pastas e devem ser escapadas se o nome de uma etiqueta contiver uma barra. As seguintes opções são suportadas:
    • Work“: esta é a etiqueta ou pasta chamada ‘Work’
    • Work/Project1“: esta é a subpasta ‘Project1’ que está na pasta ‘Work’
    • Work/Project1/Docs“: esta é a subpasta ‘Docs’ que está na subpasta ‘Project1’ que está na pasta ‘Work’
    • Work/Misc\\/Others“: esta é a subpasta ‘Misc/Others’ que está na pasta ‘Work’
  • Consulte: Introdução

Imap4flags

Rejeitar

Vacation

Variáveis

Relacional

  • Utilização: relational
  • Descrição: Fornece operadores de correspondência relacional.
  • Documentação: https://tools.ietf.org/html/rfc5231

Regex

  • Utilização: regex
  • Descrição: Fornece os operadores de correspondência regex.
  • Documentação: https://tools.ietf.org/id/draft-ietf-sieve-regex-01.html

Comparador numérico ASCII

Listas armazenadas externamente

  • Utilização: extlists
  • Descrição: Fornece acesso a listas de contactos.
  • Documentação: https://tools.ietf.org/html/rfc6134(nova janela)
  • Implementação: As seguintes listas são suportadas
    • addrbook:personal : Lista de contactos pessoais. As seguintes consultas são suportadas:
      • label[.starts-with / .ends-with / .contains]=<group: string>: operação num grupo de contactos;
      • keypinning=<value: true / false> definição de chave pública do contacto;
      • encryption=<value: true / false> encriptação predefinida do contacto;
      • signing=<value: true / false>  assinatura predefinida do contacto.
    • :addrbook:myself Endereços pertencentes ao utilizador atual;
    • :addrbook:organization Endereços pertencentes aos membros da organização atual;
    • :incomingdefaults:inbox Lista de endereços permitidos
    • :incomingdefaults:spam Lista de endereços bloqueados
  • Ver: Aceder à sua lista de contactos

Eval

  • Utilização: vnd.proton.eval
  • Descrição: Avalia uma função aritmética simples fornecida numa string.
  • Documentação: Transformar variáveis

Include

Expiração

  • Utilização: vnd.proton.expire
  • Descrição: Gere a expiração de mensagens.
  • Documentação: Gerir a expiração

Testes

Currentdate

  • Utilização:
currentdate [":zone" <time-zone: string>] [COMPARATOR] [MATCH-TYPE] <date-part: string> <key-list: string-list>

Data

  • Utilização:
date [":zone" <time-zone: string> / ":originalzone"] [MATCH-TYPE] <header-name: string> <date-part: string> <key-list: string-list

HasFlag

  • Utilização:
hasflag [MATCH-TYPE] [COMPARATOR] <list-of-flags: string-list>
  • Descrição: Verifica se uma determinada mensagem tem uma determinada flag.
  • Pacote: imap4flags
  • Consulte: Introdução

Envelope

  • Utilização:
envelope [COMPARATOR] [ADDRESS-PART] [MATCH-TYPE] <envelope-part: string-list> <key-list: string-list>

Endereço·

  • Utilização:
address [COMPARATOR] [ADDRESS-PART] [MATCH-TYPE] <header-list: string-list> <key-list: string-list>
  • Descrição: Verifica se o(s) cabeçalho(s) especificado(s) analisado(s) como um endereço corresponde(m) à(s) chave(s) especificada(s).
  • Pacote: <predefinição>
  • Consulte: Comparação com endereços no Sieve

Cabeçalho

  • Utilização:
header [COMPARATOR] [MATCH-TYPE] <header-names: string-list> <key-list: string-list>

HasExpiration

  • Utilização:
hasexpiration
  • Descrição: Verifica se uma mensagem tem um tempo de expiração definido.
  • Pacote: vnd.proton.expire

Exists

  • Utilização:
exists <header-names: string-list>

Expiração

  • Utilização:
expiration :comparator "i;ascii-numeric" [MATCH-TYPE] <unit: "day" / "minute" / "second"> <key-list: string-list>
  • Descrição: Compara o tempo de expiração da mensagem com a(s) chave(s) fornecida(s). O teste falhará se for executado numa mensagem que não expira.
  • Pacote: vnd.proton.expire

Size

  • Utilização:
size <":over" / ":under"> <limit: number>

String

  • Utilização:
string [MATCH-TYPE] [COMPARATOR] <source: string-list> <key-list: string-list>
  • Descrição: Avalia se alguma das cadeias de caracteres de origem corresponde a alguma chave.
  • Pacote: variables

Anyof

  • Utilização:
anyof <tests: test-list>
  • Descrição: Efetua um OR lógico nos testes que lhe são fornecidos.
  • Pacote: <predefinição>
  • Consulte: Introdução

Allof

  • Utilização:
allof <tests: test-list>
  • Descrição: Efetua um AND lógico nos testes que lhe são fornecidos.
  • Pacote: <predefinição>
  • Consulte: Introdução

Not

  • Utilização:
not <test: test>
  • Descrição: Inverte o resultado do teste fornecido.
  • Pacote: <predefinição>
  • Consulte: Introdução

True

  • Utilização:
true
  • Descrição: Corresponde sempre.
  • Pacote: <predefinição>

False

  • Utilização:
false
  • Descrição: Nunca corresponde.
  • Pacote: <predefinição>

Acções

Require

  • Utilização:
require <packages: string-list>
  • Descrição: Carrega uma extensão especificada para que os seus métodos ou modificações possam ser utilizados.
  • Pacote: <predefinição>
  • Consulte: Introdução

FileInto

  • Utilização:
fileinto <folder: string>
  • Descrição: Move a mensagem que está a ser processada para uma determinada pasta.
  • Pacote: fileinto
  • Consulte: Introdução

Addflag

  • Utilização:
addflag <list-of-flags: string-list>
  • Descrição: Adiciona a flag especificada à mensagem que está a ser processada.
  • Pacote: imap4flags
  • Consulte: Introdução

Removeflag

  • Utilização:
removeflag <list-of-flags: string-list>
  • Descrição: Remove as flags especificadas da mensagem que está a ser processada.
  • Pacote: imap4flags

Setflag

  • Utilização:
setflag <list-of-flags: string-list>
  • Descrição: Remove todas as marcações e define as marcações especificadas na mensagem que está a ser processada.
  • Pacote: imap4flags

Stop

  • Utilização:
stop
  • Descrição: Para o processamento de todos os filtros Sieve. Os filtros Sieve subsequentes não serão executados.
  • Pacote: <predefinição>

Return

  • Utilização:
return
  • Descrição: Para o processamento do filtro Sieve atual. Os filtros Sieve subsequentes continuarão a ser executados.
  • Pacote: include

Set

  • Utilização:
set [MODIFIER] <name: string> <value: string>
  • Descrição: Cria novas variáveis associando o nome e o valor fornecidos.
  • Pacote: variables
  • Ver: Criar variáveis

Discard

  • Utilização:
discard
  • Descrição: Descarta a mensagem no final deste filtro Sieve. Após descartar, nenhum outro filtro Sieve será executado.
  • Pacote: <predefinição>

Keep

  • Utilização:
keep
  • Descrição: Reverte o último comando de descarte. Apenas terá efeito se estiver no mesmo filtro Sieve. Se nenhum descarte tiver sido executado, este comando não fará nada.
  • Pacote: <predefinição>

Rejeitar

  • Utilização:
reject <reason: string>
  • Descrição: Envia um e-mail para o endereço SMTP do remetente com o motivo e descarta esta mensagem instantaneamente. O comando keep não irá cancelar esta ação.
  • Pacote: <predefinição>
  • Consulte: Introdução, Mensagens de férias e testes de data

Expire

  • Utilização:
expire <unit: "day" / "minute" / "second"> <value: string>
  • Descrição: Expira uma mensagem após o tempo indicado.
  • Pacote: vnd.proton.expire
  • Consulte: Gestão da expiração

Unexpire

  • Utilização:
unexpire
  • Descrição: Remove o tempo de expiração de uma mensagem.
  • Pacote: vnd.proton.expire

Vacation

  • Utilização:
vacation [":days" number] [":subject" string] [":mime"] [":handle" string] <reason: string>
  • Descrição: Envia uma resposta automática para o endereço SMTP do remetente com o motivo especificado como corpo.
  • Pacote: vacation (requer uma conta paga)
  • Consulte: Mensagens de férias e testes de data

Lista externa válida

  • Utilização:
valid_ext_list <ext-list-names: string-list>
  • Descrição: Testa se todas as listas externas fornecidas são suportadas e válidas.
  • Pacote: extlists