> ## Documentation Index
> Fetch the complete documentation index at: https://docs.endorlabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

<AgentInstructions>

## Submitting Feedback

If you encounter incorrect, outdated, or confusing documentation on this page, submit feedback:

POST https://docs.endorlabs.com/feedback

```json
{
  "path": "/integrations/email/index",
  "feedback": "Description of the issue"
}
```

Only submit feedback when you have something specific and actionable to report.

</AgentInstructions>

# Set up email integration

> Learn how to integrate your email addresses with Endor Labs and receive finding notifications

export const CodeFile = ({src, lang, expandable = true, maxLines = 15}) => {
  const [content, setContent] = useState(null);
  const [wrapperLang, setWrapperLang] = useState('text');
  const [error, setError] = useState('');
  const [copied, setCopied] = useState(false);
  const [isDark, setIsDark] = useState(false);
  const [expanded, setExpanded] = useState(false);
  useEffect(() => {
    const root = document.documentElement;
    setIsDark(root.classList.contains('dark'));
    const observer = new MutationObserver(() => {
      setIsDark(root.classList.contains('dark'));
    });
    observer.observe(root, {
      attributes: true,
      attributeFilter: ['class']
    });
    return () => {
      observer.disconnect();
    };
  }, []);
  useEffect(() => {
    if (!src) {
      setError('No src provided.');
      return undefined;
    }
    const ac = new AbortController();
    fetch(src, {
      signal: ac.signal
    }).then(r => {
      if (!r.ok) throw new Error(r.status + ' ' + r.statusText);
      return r.json();
    }).then(data => {
      setContent(data.content || '');
      if (data.lang) setWrapperLang(data.lang);
    }).catch(err => {
      if (err.name !== 'AbortError') {
        setError('Unable to load ' + src + ': ' + err.message);
      }
    });
    return () => {
      ac.abort();
    };
  }, [src]);
  const language = lang || wrapperLang || 'text';
  const handleCopy = () => {
    if (!content) return;
    navigator.clipboard.writeText(content).then(() => {
      setCopied(true);
      setTimeout(() => {
        setCopied(false);
      }, 2000);
    }).catch(() => {});
  };
  const toggleExpand = () => {
    setExpanded(v => !v);
  };
  const statusBoxStyle = variant => {
    const base = {
      padding: '12px 16px',
      borderRadius: '6px',
      fontSize: '14px'
    };
    if (variant === 'error') {
      return {
        ...base,
        background: isDark ? '#451a1a' : '#fef2f2',
        color: isDark ? '#fca5a5' : '#dc2626',
        border: '1px solid ' + (isDark ? '#7f1d1d' : '#fecaca')
      };
    }
    return {
      ...base,
      background: isDark ? '#1f2937' : '#f5f5f5',
      color: isDark ? '#9ca3af' : '#6b7280'
    };
  };
  const shellStyle = {
    position: 'relative',
    borderRadius: '8px',
    border: '1px solid ' + (isDark ? 'rgba(255,255,255,0.1)' : '#d1d5db'),
    overflow: 'hidden'
  };
  const copyBtnStyle = {
    position: 'absolute',
    top: '8px',
    right: '8px',
    padding: '4px 8px',
    fontSize: '12px',
    lineHeight: '1',
    border: '1px solid rgba(255,255,255,0.3)',
    borderRadius: '4px',
    background: 'rgba(255,255,255,0.15)',
    color: '#fff',
    cursor: 'pointer',
    zIndex: 2,
    transition: 'background 0.15s, color 0.15s'
  };
  const renderErrorBox = () => <div style={statusBoxStyle('error')}>{error}</div>;
  const renderLoadingBox = () => <div style={statusBoxStyle('loading')}>Loading…</div>;
  const countLogicalLines = text => {
    const normalized = text.replace(/\n+$/, '');
    if (normalized === '') {
      return 0;
    }
    return normalized.split('\n').length;
  };
  const lineCount = content ? countLogicalLines(content) : 0;
  const showTruncate = expandable && lineCount >= maxLines && !expanded;
  const showExpandToggle = expandable && lineCount >= maxLines;
  const LINE_HEIGHT_PX = 25;
  const previewMaxHeightPx = maxLines * LINE_HEIGHT_PX;
  const preStyle = {
    margin: 0,
    padding: '16px',
    overflow: 'auto',
    maxHeight: showTruncate ? previewMaxHeightPx + 'px' : 'none',
    overflowY: showTruncate ? 'hidden' : 'auto'
  };
  const toggleLinkStyle = {
    display: 'block',
    width: '100%',
    boxSizing: 'border-box',
    background: 'none',
    border: 'none',
    padding: '8px 16px 12px 16px',
    cursor: 'pointer',
    color: '#26D07C',
    fontSize: '13px',
    fontFamily: 'inherit',
    textAlign: 'left'
  };
  const renderLoaded = () => <div style={shellStyle}>
      <button type="button" onClick={handleCopy} aria-label="Copy code" style={copyBtnStyle} onMouseEnter={e => {
    e.currentTarget.style.background = 'rgba(255,255,255,0.25)';
  }} onMouseLeave={e => {
    e.currentTarget.style.background = 'rgba(255,255,255,0.15)';
  }}>
        {copied ? 'Copied!' : 'Copy'}
      </button>
      <pre style={preStyle}>
        <code className={'language-' + language} style={{
    fontSize: '14px'
  }}>
          {content}
        </code>
      </pre>
      {showExpandToggle ? <button type="button" style={toggleLinkStyle} onClick={toggleExpand} aria-expanded={expanded ? 'true' : 'false'} aria-label={expanded ? 'Show less code' : 'See all ' + lineCount + ' lines of code'}>
          {expanded ? '... Show less' : '... See all ' + lineCount + ' lines'}
        </button> : null}
    </div>;
  if (error) {
    return renderErrorBox();
  }
  if (content === null) {
    return renderLoadingBox();
  }
  return renderLoaded();
};

Integrate your email address with Endor Labs and automatically receive policy violations as email notifications.

* [Configure email integration](#configure-email-integration)
  * [Associate an action policy with the email notification](#associate-an-action-policy-with-the-email-notification)
  * [Customize email notification templates](#customize-email-notification-templates)
  * [Data model](#data-model)
* [Run a scan](#run-a-scan)

## Configure email integration

To configure an email integration, follow these steps:

1. Sign in to Endor Labs and select **Integrations** from the left sidebar.
2. Navigate to **Email** under **Notifications** and click **Add**.
3. Click **Add Notification Integration**.
4. Specify a name and description for this integration.
5. Enter email addresses separated by commas in  **EMAIL ADDRESSES**.
6. Click **Add Notification Integration**.

### Associate an action policy with the email notification

Users can create action policies to send an email notification when a scan matches policy conditions. For example, if there is a critical or high vulnerability, send an email notification.

While creating an action policy, configure the following settings:

* Select **Choose an Action** as **Send Notification**.

* From **SELECT NOTIFICATION TARGETS**, choose the email integration notification that you created.

* Choose an **Aggregation type** for notifications.
  * Choose **None (Notify for each Finding)** to trigger a separate email for each finding.
  * Choose **Project** to group and send all the findings related to a project in one email.
  * Choose **Dependency** to send individual emails for every dependency.
  * Choose **Dependency per package version** to send emails for every unique combination of dependency and package version.

* From **Assign Scope**, include the project tags in **INCLUSIONS** to apply this policy to a project.

See [Create an action policy](/platform-administration/policies/action-policies) for more details.

### Customize email notification templates

Endor Labs provides a default template with standard information for the email. You can use the default template or you can choose to edit and customize this template to fit your organization's specific requirements. You can also create custom templates using [Go Templates](https://pkg.go.dev/text/template).

1. Sign in to Endor Labs and select **Integrations** from the left sidebar.
2. Look for **Email** under **Notifications**.
3. Click **Manage** to view the list of configured notification integrations.
4. Choose a notification integration and click the ellipsis on the right side, and click **Edit Template**.
5. Make required changes to any of the following templates and click **Save Template**.
   * **Open** - This template applies when Endor Labs raises new notifications.
   * **Update** - This template applies when an existing notification updates, such as when findings change.
   * **Resolve** - This template applies when all findings reported by the notification resolve.
6. Click **Restore to Default** to revert the changes.
7. Use the download icon on the top right corner to download this template.
8. Use the copy icon to copy the information in the template.

### Data model

To create custom templates for email notifications, you must understand the data supplied to the template.

See the `EmailData` message used for **Open** and **Update** templates.

<CodeFile src="/templates/notifications/email_data.json" lang="go" />

See the `ResolvedEmailData` message used for **Resolve** template.

<CodeFile src="/templates/notifications/resolved_email_data.json" lang="go" />

See the following protobuf specification for the `NotificationData` message referenced by `EmailData`.

<CodeFile src="/templates/notifications/notification_data.json" lang="proto" />

To understand Project, Finding, PackageVersion and RepositoryVersion definitions in this protobuf specification, see:

* [Project resource kind](/developers-api/rest-api/using-the-rest-api/data-model/resource-kinds#project)
* [Finding resource kind](/developers-api/rest-api/using-the-rest-api/data-model/resource-kinds#finding)
* [PackageVersion resource kind](/developers-api/rest-api/using-the-rest-api/data-model/resource-kinds#packageversion)
* [RepositoryVersion resource kind](/developers-api/rest-api/using-the-rest-api/data-model/resource-kinds#repositoryversion)

See the following specification to understand a few additional functions available to the template. You can access these functions by using their corresponding keys.

<CodeFile src="/templates/notifications/email_notification_func_map.json" lang="go" />

## Run a scan

Run the endorctl scan on your configured projects. See [endorctl scan commands](/developers-api/cli/commands/scan) for more information.
You can view email notifications of policy violations in your inbox.
