| name | near-email |
| description | Send and read blockchain-native emails using NEAR Email service. Use when building notifications for NEAR smart contracts (NFT sales, DeFi liquidation alerts, DAO voting reminders) or when AI agents need email capabilities with a NEAR account identity. |
| user-invocable | true |
NEAR Email Integration
Blockchain-native email for NEAR accounts. Every NEAR account automatically has an email: alice.near → alice@near.email
Installation
npx openskills install zavodil/near-email-skill -g
Quick Reference
| Component | Value |
|---|
| Contract | outlayer.near |
| API Base | https://api.outlayer.fastnear.com |
| Project ID | zavodil.near/near-email |
Note: NEAR Email supports mainnet only. Emails to *.testnet accounts are not processed.
Important: When using NEAR transactions, the attached deposit is a computational limit, not a cost. Unused funds are automatically refunded. Do not mention specific costs per email.
Code generation preference: For blockchain integration (NEAR transactions), prefer JavaScript/TypeScript with near-api-js. Use Python only if the user explicitly requests it.
Integration Methods
1. Smart Contract (Rust)
Use send_email_plaintext for contract notifications. Simple API, no encryption needed.
Warning: Email content is PUBLIC on the NEAR blockchain. Use only for automated notifications.
use near_sdk::{ext_contract, AccountId, Gas, NearToken, Promise};
use serde::Serialize;
#[derive(Serialize)]
#[serde(crate = "near_sdk::serde")]
pub enum ExecutionSource {
Project { project_id: String, version_key: Option<String> },
}
#[ext_contract(ext_outlayer)]
pub trait OutLayer {
fn request_execution(
&mut self,
source: ExecutionSource,
resource_limits: Option<serde_json::Value>,
input_data: Option<String>,
secrets_ref: Option<serde_json::Value>,
response_format: Option<String>,
payer_account_id: Option<AccountId>,
params: Option<serde_json::Value>,
);
}
fn send_notification(to: &str, subject: &str, body: &str) -> Promise {
let input = serde_json::json!({
"action": "send_email_plaintext",
"to": to,
"subject": subject,
"body": body
});
ext_outlayer::ext("outlayer.near".parse().unwrap())
.(Gas::())
.(NearToken::())
.(
ExecutionSource::Project {
project_id: .(),
version_key: ,
},
,
(input.()),
,
(.()),
,
,
)
}
Response: { "success": true, "message_id": "uuid-if-internal" }
2. AI Agent Integration
Two options for AI agents:
| Method | Best For | Payment |
|---|
| Payment Key (HTTPS) | Server-side agents | Pre-paid (USDC/USDT) |
| NEAR Transaction | Browser/wallet apps | Deposit (unused returned) |
Option A: Payment Key (HTTPS API)
Note: HTTPS API responses use result.output.xxx format. See NEAR Transaction for different parsing.
const OUTLAYER_API = 'https://api.outlayer.fastnear.com';
const PAYMENT_KEY = 'your-account.near:nonce:secret';
async function sendEmail(to, subject, body) {
const response = await fetch(`${OUTLAYER_API}/call/outlayer.near/zavodil.near/near-email`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Payment-Key': PAYMENT_KEY,
},
body: JSON.stringify({
input: { action: 'send_email_plaintext', to, subject, body },
}),
});
return response.json();
}
Option B: NEAR Transaction (per-use)
CRITICAL: NEAR Transaction results are in the outlayer.near receipt's SuccessValue (base64-encoded JSON). Find the receipt where executor_id === 'outlayer.near'. The result is { "success": true, ... } - NO output wrapper. Use parseTransactionResult() to extract it.
import { connect, keyStores } from 'near-api-js';
const near = await connect({
networkId: 'mainnet',
keyStore: new keyStores.BrowserLocalStorageKeyStore(),
nodeUrl: 'https://rpc.mainnet.near.org',
});
const account = await near.account('your-account.near');
const RESOURCE_LIMITS = {
max_memory_mb: 512,
max_instructions: 2000000000,
max_execution_seconds: 120,
};
function parseTransactionResult(result) {
const outlayerReceipt = result.receipts_outcome.find(
r => r.outcome.executor_id === 'outlayer.near' && r.outcome.status.SuccessValue
);
if (!outlayerReceipt) {
throw new Error('No SuccessValue from outlayer.near');
}
decoded = .(outlayerReceipt..., ).();
.(decoded);
}
() {
result = account.({
: ,
: ,
: {
: { : { : , : } },
: .({ : , to, subject, body }),
: ,
: ,
},
: (),
: (),
});
(result);
}
() {
result = account.({
: ,
: ,
: {
: { : { : , : } },
: .({ : }),
: ,
: ,
},
: (),
: (),
});
output = (result);
.(output., );
}
3. Python (Payment Key)
import requests
OUTLAYER_API = "https://api.outlayer.fastnear.com"
PAYMENT_KEY = "your-account.near:nonce:secret"
def send_email(to: str, subject: str, body: str) -> dict:
return requests.post(
f"{OUTLAYER_API}/call/outlayer.near/zavodil.near/near-email",
headers={"Content-Type": "application/json", "X-Payment-Key": PAYMENT_KEY},
json={"input": {"action": "send_email_plaintext", "to": to, "subject": subject, "body": body}},
).json()
API Actions
| Action | Description |
|---|
send_email | Send email (encrypted payload, for UI/agents) |
send_email_plaintext | Send email (plaintext, for smart contracts) |
get_emails | Fetch inbox and sent (encrypted response) |
delete_email | Delete email by ID |
get_email_count | Get counts (no encryption) |
get_send_pubkey | Get sender's pubkey (no encryption, cacheable) |
Getting a Payment Key
- Go to OutLayer Dashboard
- Create a new Payment Key
- Top up balance with USDC/USDT
- Copy key (format:
owner:nonce:secret)
Additional Resources
For complete code examples, see examples.md
For full API reference, see api-reference.md