=VERIFY_EMAIL() a =FIND_EMAIL() v Google Sheets
- Pro koho
- Lidé, kteří vedou seznamy leadů v Google Sheets
- Problém
- Exportovat list do ověřovacího nástroje a vkládat výsledky zpět je zdlouhavé. Naivní vlastní funkce volá API znovu, a znovu utratí kredit, pokaždé, když Sheets vzorec spustí znovu.
- Řešení
- Dvě vlastní funkce volají API Cold Leads přes UrlFetchApp, klíč čtou z vlastností skriptu a každou odpověď drží v cache skriptu až šest hodin, takže opakované spuštění stejného vzorce za stejný vstup další kredit neutratí.
- Co získáte
- Tři buňky s výsledkem na řádek: stav, skóre a důvod z =VERIFY_EMAIL, nebo adresa, metoda a míra jistoty z =FIND_EMAIL.
Adresy, identifikátory a výsledky v příkladech jsou ilustrativní. Doména example.com je vyhrazená pro dokumentaci, takže skutečná kontrola těchto adres vrátí invalid.
Ukázky kódu jsou ve všech jazycích stejné, komentáře v nich jsou anglicky.
Nastavení
- V tabulce otevřete Extensions → Apps Script a obsah Code.gs nahraďte skriptem níže. Uložte.
- Klikněte na Project Settings a pak v části Script Properties na Add script property. Property: COLDLEADS_API_KEY, value: váš tajný klíč Cold Leads (sk_…). Klikněte na Save script properties.
- Zpět v listu napište do B2 =VERIFY_EMAIL(A2). Výsledek vyplní B2, C2 a D2 (status, score, reason), takže ty dvě buňky vpravo nechte prázdné. Vzorec roztáhněte dolů.
- Pro adresy, které ještě nemáte, napište =FIND_EMAIL(B2, C2, D2) s křestním jménem, příjmením a doménou nebo webem firmy. Funkce vyplní adresu, metodu a míru jistoty.
Skript
// Cold Leads custom functions for Google Sheets (Extensions → Apps Script, paste into Code.gs).
// Key: Project Settings → Script Properties → Add script property COLDLEADS_API_KEY = sk_...
const COLDLEADS_API = 'https://coldleads.app/api/v1';
const CACHE_SECONDS = 21600; // 6 hours, the longest CacheService keeps an entry
/**
* Verifies an e-mail address with Cold Leads. Fills three cells: status, score, last reason code.
* Costs 1 Cold Leads credit unless the same address was answered from this script's cache.
*
* @param {string} email The address, for example A2.
* @return Status, score and reason.
* @customfunction
*/
function VERIFY_EMAIL(email) {
const address = String(email || '').trim().toLowerCase();
if (!address) return '';
const r = cachedCall_('verify:' + address, '/verify', { email: address, timeout_ms: 20000 }, function (res) {
return res.reasons[res.reasons.length - 1] !== 'timeout'; // timeouts are worth checking again
});
return [[r.status, r.score, r.reasons[r.reasons.length - 1]]];
}
/**
* Finds the most likely e-mail address for a person at a company domain. Fills three cells:
* address, method ("verified" only when a mail server confirmed the mailbox, otherwise "pattern"), confidence.
* Costs 1 Cold Leads credit unless answered from this script's cache.
*
* @param {string} first First name, for example B2.
* @param {string} last Last name, for example C2.
* @param {string} domain Company domain or website, for example D2.
* @return Address, method and confidence.
* @customfunction
*/
function FIND_EMAIL(first, last, domain) {
const body = { first: String(first || '').trim(), last: String(last || '').trim(), domain: String(domain || '').trim().toLowerCase() };
if (!body.domain || !(body.first || body.last)) return '';
const key = 'find:' + [body.first, body.last, body.domain].join('|').toLowerCase();
const r = cachedCall_(key, '/find', body, function () { return true; });
return [[r.email || '', r.method, r.confidence]];
}
function cachedCall_(cacheKey, path, payload, cacheable) {
const cache = CacheService.getScriptCache();
// cache keys are limited to 250 characters, so store a hash of the key
const id = Utilities.base64Encode(Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, cacheKey, Utilities.Charset.UTF_8));
const hit = cache.get(id);
if (hit) return JSON.parse(hit);
const apiKey = PropertiesService.getScriptProperties().getProperty('COLDLEADS_API_KEY');
if (!apiKey) throw new Error('Add the script property COLDLEADS_API_KEY (Project Settings → Script Properties).');
const res = UrlFetchApp.fetch(COLDLEADS_API + path, {
method: 'post',
contentType: 'application/json',
headers: { 'x-api-key': apiKey },
payload: JSON.stringify(payload),
muteHttpExceptions: true,
});
const data = JSON.parse(res.getContentText() || '{}');
if (res.getResponseCode() !== 200) throw new Error('Cold Leads: ' + (data.error || 'HTTP ' + res.getResponseCode()));
if (cacheable(data)) cache.put(id, JSON.stringify(data), CACHE_SECONDS);
return data;
}Jak se chová
- Sheets spustí vlastní funkci znovu, když upravíte vzorec, zkopírujete ho do jiné buňky nebo změníte buňku, na kterou odkazuje. Bez cache je každé spuštění nové volání API a nový kredit.
- Cache skriptu drží každou odpověď až 6 hodin a sdílejí ji všichni, kdo skript používají. Google může položky zahodit dřív, když je cache plná, a uvádí, že Cache service ve vlastních funkcích funguje, ale „není tam nijak zvlášť užitečná“; zde jen brání tomu, abyste za stejný vstup platili dvakrát.
- Odpovědi s důvodem timeout se do cache neukládají, takže další spuštění adresu zkontroluje znovu.
- Vlastní funkce musí skončit do 30 sekund. =VERIFY_EMAIL žádá Cold Leads o časový limit 20 sekund. =FIND_EMAIL žádný limit nemá a u domény, kde se kontroluje několik kandidátních adres, může 30 sekund překročit; buňka pak ukáže chybu a kredit už je utracený.
- Kdokoli, kdo může tabulku upravovat, může otevřít její projekt Apps Script, a tím i klíč. Oprávnění k úpravám dávejte jen lidem, kteří smějí klíč používat, a pokud se to změní, přegenerujte klíč v Cold Leads (Nastavení → API klíče).
Jak číst výsledky
| Funkce | Výsledek | Význam |
|---|---|---|
| VERIFY_EMAIL | valid, 97 nebo 80, ok | Poštovní server schránku přijal (80 u rolových adres jako info@). |
| VERIFY_EMAIL | valid, 75 nebo 65, smtp_unreachable | Doména přijímá poštu, ale samotná schránka se nekontrolovala. |
| VERIFY_EMAIL | risky, catch_all nebo smtp_unknown | Server přijímá jakoukoli adresu, nebo nedal jednoznačnou odpověď. |
| VERIFY_EMAIL | risky, timeout | Kontrole došel čas; příště proběhne znovu. |
| VERIFY_EMAIL | invalid, mailbox_missing, no_mx nebo syntax | Adresu nepoužívejte. |
| FIND_EMAIL | adresa, verified | Poštovní server schránku potvrdil. |
| FIND_EMAIL | adresa, pattern | Odhad z běžných formátů adres; před použitím ho potvrďte. |
| FIND_EMAIL | prázdné, none | Žádný kandidát: doména nemá poštovní server, nebo jméno nešlo použít. |
Limity a náklady
- 1 kredit Cold Leads za každé volání, na které neodpoví cache skriptu. Cold Leads účtuje i výsledky ze své vlastní 30denní cache, takže kredity šetří právě cache skriptu.
- Apps Script povoluje 20 000 volání URL Fetch denně u osobních účtů a 100 000 u Google Workspace a 30 sekund na jedno volání vlastní funkce. Vyplnění vzorce do tisíců řádků najednou může selhat s chybou Script invoked too many times per second; vyplňujte po menších blocích, nebo pro velké seznamy použijte hromadnou úlohu.
- Cold Leads povoluje 120 požadavků za minutu na klíč. API je součástí tarifu Business: $99 měsíčně s 10 000 kredity měsíčně; další balíčky po 1 000 kreditech stojí $5.
Otázky
Buňka ukazuje #ERROR!. Co se stalo?
Najeďte myší na buňku a přečtěte si zprávu: chybějící vlastnost COLDLEADS_API_KEY, chyba Cold Leads jako no_credits nebo rate_limited, nebo 30sekundový limit vlastních funkcí.
Stojí znovuotevření tabulky kredity?
Sheets spouští vlastní funkci znovu hlavně tehdy, když se změní její vzorec nebo vstupní buňky. Pokud se přece jen spustí znovu se stejným vstupem do šesti hodin, odpoví cache skriptu bez volání Cold Leads.
Jak zkontrolovat tisíce adres?
Místo vlastní funkce použijte hromadnou úlohu: až 5 000 adres na požadavek a dotazování na stav až do dokončení. Kompletní verze ukazují stránky o n8n a Pythonu na tomto webu.