Our team is currently working on this feature. If you experience any bugs, please let us know on our Discord. We appreciate your patience.
Email Significance
Many online services, from social media platforms to e-commerce sites, require an email address to create an account. According to recent surveys, more than 80% of businesses consider email to be their primary communication channel, both internally and with customers.
All of this means that our inboxes are full of data that can be leveraged.
Proof of Email
With vlayer, you can access email content from smart contracts and use it on-chain.
You do this by writing a Solidity smart contract (Prover
) that has access to the parsed email and returns data to be used on-chain. This allows you to create claims without exposing the full content of an email.
Under the hood, we verify mail server signatures to ensure the authenticity and integrity of the content.
Email Safety Requirements
Not all emails that are considered valid by email servers will meet the validity requirements for vlayer. Email servers use various rules based on DMARC, DKIM, and SPF to determine if an email is valid. When creating an Email Proof, only DKIM (DomainKeys Identified Mail) signatures are used to prove the authenticity of an email. Therefore, the following additional preconditions must be met:
- The email must be signed with a DKIM-Signature header.
- The email must be sent from a domain that has a valid DKIM record.
- The email must have exactly one DKIM signature with a
d
tag that matches the domain of theFrom
header. - The email must have a signed
From
header containing a single email address.
If the email doesn't have a DKIM signature with matching signer and sender domains, it may indicate that the sender's email server is misconfigured. Emails from domains hosted on providers like Google Workspaces or Outlook often have a DKIM signature resembling the following:
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=***.gappssmtp.com; s=20230601; dara=google.com;
h=...;
bh=...;
b=...
Another potential issue is the use of subdomains.
For example, if the email is sent from [email protected]
and the d
tag in the DKIM signature is example.com
, the email will not be considered valid.
Similarly, if the email is sent from [email protected]
and the d
tag is subdomain.example.com
, the email will also be invalid.
DKIM validation will fail if the email body has been modified by a proxy server. The body hash included in the DKIM signature ensures the integrity of the email’s content. Any alteration to the body will invalidate the signature.
Example
Let's say someone wants to prove they are part of company or organization. One way to do this is to take a screenshot and send it to the verifier. However, this is not very reliable because screenshot images can be easily manipulated, and obviously such an image cannot be verified on-chain.
A better option is to prove that one can send email from it's organization domain. Below is a sample Prover
contract that verifies that the sender sent email from a specific domain.
Below is an example of such proof generation:
import {Strings} from "@openzeppelin-contracts-5.0.1/utils/Strings.sol";
import {Proof} from "vlayer-0.1.0/Proof.sol";
import {Prover} from "vlayer-0.1.0/Prover.sol";
import {VerifiedEmail, UnverifiedEmail, EmailProofLib} from "vlayer-0.1.0/EmailProof.sol";
import {EmailStrings} from "./EmailStrings.sol";
contract EmailDomainProver is Prover {
using Strings for string;
using EmailStrings for string;
using EmailProofLib for UnverifiedEmail;
string targetDomain;
constructor(string memory _targetDomain) {
targetDomain = _targetDomain;
}
function main(UnverifiedEmail calldata unverifiedEmail, address targetWallet)
public
view
returns (Proof memory, bytes32, address)
{
VerifiedEmail memory email = unverifiedEmail.verify();
require(email.from.contains(targetDomain), "incorrect sender domain");
require(email.subject.equal("Verify me for company NFT"), "incorrect subject");
return (proof(), sha256(abi.encodePacked(email.from)), targetWallet);
}
}
It can be convenient to use Regular Expressions to validate the content of the email.
Email is passed to the Solidity contract as an UnverifiedEmail
structure that can be created using the preverifyEmail
function in the SDK.
preverifyEmail
should be called with the raw .eml
file content as an argument (learn how to get this file). The email is also required to have From
and DKIM-Signature
headers.
struct UnverifiedEmail {
string email;
string[] dnsRecords;
}
First, we verify the integrity of the email with the verify()
function. Then we have a series of assertions (regular Solidity require()
) that check the email details.
If one of the string comparisons fails, require will revert the execution, and as a result, proof generation will fail.
💡 Try it Now
To run the above example on your computer, type the following command in your terminal:
vlayer init --template simple-email-proof
This command will download create and initialise a new project with sample email proof contracts.
Email structure
The email
structure of type VerifiedEmail
is a result of the UnverifiedEmail.verify()
function.
Since the verify
function actually verifies the passed email, VerifiedEmail
's fields can be trusted from this point.
struct VerifiedEmail {
string from;
string to;
string subject;
string body;
}
An VerifiedEmail
consists of the following fields:
from
- a string consisting of the sender's email address (no name is available);to
- a string consisting of the intended recipient's email address (no name is available);subject
- a string with the subject of the email;body
- a string consisting of the entire body of the email.
By inspecting and parsing the email payload elements, we can generate a claim to be used on-chain.
Getting .eml
Files
Obtaining an .eml
file can be helpful for development purposes, such as testing own email proofs. Below are instructions for retrieving .eml
files from common email clients.
Gmail
- Open the email you want to save.
- Click the three-dot menu in the top-right corner of the email.
- Select Download message.
Outlook / Thunderbird
- Open the email you want to save.
- Click on the File menu.
- Select "Save As".
Security Assumptions
Billions of users trust providers to deliver and store their emails. Inboxes often contain critical information, including work-related data, personal files, password recovery links, and more. Email providers also access customer emails for purposes like serving ads. Email proofs can only be as secure as the email itself, and the protocol relies on the trustworthiness of both sending and receiving servers.
Outgoing Server
The vlayer prover verifies that the message signature matches the public key listed in the DNS records. However, a dishonest outgoing server can forge emails and deceive the prover into generating valid proofs for them. To mitigate this risk, vlayers support only a limited number of the world's most trusted email providers.
Preventing Unauthorized Actions
Both outgoing and incoming servers can read emails and use them to create proofs without the permission of the actual mail sender or receiver. This risk also extends to the prover, which accesses the email to generate claims. It is crucial for protocols to utilize email proofs in a manner that prevents the manipulation of smart contracts into performing unauthorized actions, such as sending funds to unintended recipients.
For example, it is advisable to include complete information in the email to ensure correct actions. Opt for emails like: "Send 1 ETH from address X to address Y on Ethereum Mainnet" over partial instructions, like: "Send 1 ETH," where other details come from another source, such as smart contract call parameters. Another approach is to use unique identifiers that unambiguously point to the necessary details.