# Validate Emails

> Part of the NocoDB documentation (Workflows > Scripts > Examples). Index of all pages: https://nocodb.com/llms.txt. Any docs page is available as Markdown by adding `.md` to its URL.

URL: https://nocodb.com/docs/workflows/scripts/examples/validate-emails
Last updated: 2026-10-03

A NocoDB script that finds and lists all invalid email addresses in email fields to check data quality.

The script validates email addresses in your NocoDB database. It checks that they follow standard email format rules. It scans the email fields that you select and reports all records with invalid email addresses. This helps you keep data quality high and improves email delivery.

```javascript
let settings = input.config({
    title: "Validate emails",
    description: "This script will list all invalid emails for a field you pick.",
    items: [
        input.config.table("table", { label: "Table" }),
        input.config.field("field", {
            parentTable: "table",
            label: "Email field",
        }),
    ],
});

let { table, field } = settings as {
    table: Table,
    field: Field
};

let emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;

// Function to validate a single email
function validateEmail(email: string) {
    if (!email || typeof email !== 'string') {
        return { isValid: false, error: 'Empty or invalid data type' };
    }

    // Trim whitespace
    email = email.trim();

    if (email === '') {
        return { isValid: false, error: 'Empty after trimming whitespace' };
    }

    // Check length (email addresses shouldn't be longer than 254 characters)
    if (email.length > 254) {
        return { isValid: false, error: 'Email too long (>254 characters)' };
    }

    // Check for multiple @ symbols
    if ((email.match(/@/g) || []).length !== 1) {
        return { isValid: false, error: 'Invalid number of @ symbols' };
    }

    // Validate against regex
    if (!emailRegex.test(email)) {
        return { isValid: false, error: 'Invalid email format' };
    }

    // Check for consecutive dots
    if (email.includes('..')) {
        return { isValid: false, error: 'Consecutive dots not allowed' };
    }

    // Check if starts or ends with dot
    let [localPart, domain] = email.split('@');
    if (localPart.startsWith('.') || localPart.endsWith('.')) {
        return { isValid: false, error: 'Local part cannot start or end with dot' };
    }

    if (domain.startsWith('.') || domain.endsWith('.')) {
        return { isValid: false, error: 'Domain cannot start or end with dot' };
    }

    return { isValid: true, error: null };
}

// Function to handle multiple emails in one cell
function validateMultipleEmails(cellValue) {
    if (!cellValue || typeof cellValue !== 'string') {
        return [{ email: cellValue, isValid: false, error: 'Empty or invalid data type' }];
    }

    // Check if multiple emails are present (separated by common delimiters)
    let emails = [];
    let delimiters = /[,;|\n\r]/;

    if (delimiters.test(cellValue)) {
        // Multiple emails detected
        emails = cellValue.split(delimiters).map(email => email.trim()).filter(email => email !== '');
    } else {
        // Single email
        emails = [cellValue.trim()];
    }

    return emails.map(email => {
        let validation = validateEmail(email);
        return {
            email: email,
            isValid: validation.isValid,
            error: validation.error
        };
    });
}

// Fetch records from the selected table
let queryResult = await table.selectRecordsAsync({
    fields: [field],
});

// Handle pagination - load all records if there are more pages
while (queryResult.hasMoreRecords) {
    await queryResult.loadMoreRecords();
}

// Array to store validation results
let results = [];
let totalEmailsChecked = 0;
let totalInvalidEmails = 0;

// Process each record
for (let record of queryResult.records) {
    let recordName = record.name || record.id;
    let cellValue = record.getCellValue(field);

    // Validate emails in this cell
    let emailValidations = validateMultipleEmails(cellValue);

    for (let validation of emailValidations) {
        totalEmailsChecked++;

        if (!validation.isValid) {
            totalInvalidEmails++;
            results.push({
                Record: recordName,
                Email: validation.email || '(empty)',
                Error: validation.error,
                'Original Cell Value': cellValue || '(empty)'
            });
        }
    }
}

// Display results
if (results.length === 0) {
    output.text(
        `✅ All emails are valid! (${totalEmailsChecked} emails in ${queryResult.records.length} records validated)`
    );
} else {
    output.text(
        `❌ ${totalInvalidEmails} invalid emails found in ${results.length} entries. (${totalEmailsChecked} total emails in ${queryResult.records.length} records validated)`
    );

    // Group results by error type for better readability
    let errorGroups = {};
    for (let result of results) {
        if (!errorGroups[result.Error]) {
            errorGroups[result.Error] = [];
        }
        errorGroups[result.Error].push(result);
    }

    // Display grouped results
    for (let [errorType, items] of Object.entries(errorGroups)) {
        output.markdown(`\n**${errorType}** (${items.length} ${items.length === 1 ? 'email' : 'emails'}):`);
        output.table(items.map(item => ({
            Record: item.Record,
            Email: item.Email,
            'Original Cell Value': item['Original Cell Value']
        })));
    }
}
```

### Use Cases

* **Data Quality Assurance**: Make sure that all email addresses in your database have the correct format.
* **Marketing Campaign Prep**: Clean email lists before you send campaigns, to improve delivery.
* **Contact Management**: Find and fix invalid email addresses in customer databases.
* **Import Validation**: Check imported data for email format problems.
* **Compliance Auditing**: Check email data quality for regulatory compliance requirements.

### How it Works

1. **Select Email Field**: Select the email field to validate.
2. **Run Validation**: The script checks each email address against standard email format rules.
3. **Generate Report**: See a list of all records with invalid email addresses.
4. **Review Results**: Examine the invalid emails and their records.

### Requirements

* An **Email field** or **Text field** that contains email addresses
* Records with email data to validate

### Validation Rules

The script checks for these common email format problems:

| Problem                   | Example             |
| ------------------------- | ------------------- |
| **Missing @ symbol**      | `userexample.com`   |
| **Invalid domain format** | `user@domain`       |
| **Multiple @ symbols**    | `us@er@example.com` |
| **Invalid characters**    | `user@exam<ple.com` |
| **Missing local part**    | `@example.com`      |
| **Missing domain**        | `user@`             |
| **Improper spacing**      | `user @example.com` |

### Example Output

**Invalid Email Report:**

```
Record ID | Email Address | Issue
----------|---------------|--------
123       | user.example.com | Missing @ symbol
145       | admin@domain | Invalid domain format
167       | test@@example.com | Multiple @ symbols
189       | contact@exam ple.com | Invalid spacing
201       | @example.com | Missing local part
```

### Common Invalid Formats

#### Missing @ Symbol

```
❌ Invalid: johndoeexample.com
✅ Valid: johndoe@example.com
```

#### Incomplete Domain

```
❌ Invalid: admin@company
✅ Valid: admin@company.com
```

#### Extra Characters

```
❌ Invalid: user@exam<ple.com
✅ Valid: user@example.com
```

#### Spacing Issues

```
❌ Invalid: contact @example.com
✅ Valid: contact@example.com
```

### Benefits

* **Data Quality**: Keep email data quality high for better communication.
* **Deliverability**: Remove invalid addresses to improve email campaign success rates.
* **Error Prevention**: Find email format problems before they cause problems.
* **Compliance**: Meet data quality standards for email marketing and communication.
* **Efficiency**: Quickly find bad emails in large datasets.

### Field Types

The email validation script works with these field types:

* **Email fields**: The dedicated email fields in NocoDB
* **Text fields**: All text fields that contain email addresses
* **Single Line Text**: Standard text fields with email content

---

## Related pages

- [API Reference Manual Examples](https://nocodb.com/docs/workflows/scripts/examples/api-ref-manual-examples.md): An index of the NocoDB Scripts API reference examples, grouped by category, for common scripting tasks.
- [Find and Replace](https://nocodb.com/docs/workflows/scripts/examples/find-and-replace.md): A NocoDB script that finds and replaces text in any text-based field across records, with a preview and a confirmation.
- [Convert Attachments to URLs](https://nocodb.com/docs/workflows/scripts/examples/convert-attachments-to-urls.md): A NocoDB script that converts attachment fields into comma-separated lists of URLs for external services.
- [Randomize Values](https://nocodb.com/docs/workflows/scripts/examples/randomize-values.md): A NocoDB script that fills empty fields with random data, for many field types, with ranges and constraints that you set.
- [Get Select Options](https://nocodb.com/docs/workflows/scripts/examples/select-options.md): A NocoDB script that lists all options of a Single Select or Multiple Select field in one of three formats.
- [Save View Ordering to Field](https://nocodb.com/docs/workflows/scripts/examples/save-view-ordering.md): A NocoDB script that saves the record order of a view as sequential numbers in a numeric field.
- [Link Records by Field](https://nocodb.com/docs/workflows/scripts/examples/link-records-by-field.md): A NocoDB script that links records in two tables by matching field values, with pagination and a summary report.
- [Unique Field Values Summary](https://nocodb.com/docs/workflows/scripts/examples/unique-field-values-summary.md): A NocoDB script that shows the unique values in a field and how often each occurs, as a summary and a table.
