
Security News
How Enterprise Security Is Adapting to AI-Accelerated Threats
Socket CTO Ahmad Nassri discusses why supply chain attacks now target developer machines and what AI means for the future of enterprise security.
@bigbinary/neeto-email-notifications-frontend
Advanced tools
A repo acts as the source of truth for the new nano's structure, configs, data etc.
The neeto-email-notifications-nano is a comprehensive email notification management solution designed for the Neeto ecosystem. Implemented as a Ruby on Rails engine with associated React frontend components (@bigbinary/neeto-email-notifications-frontend), it provides a unified interface for managing email notifications across neeto applications.
Follow these steps to integrate the neeto-email-notifications-engine into your host Rails application:
Add the gem to your application's Gemfile:
# Gemfile
source "NEETO_GEM_SERVER_URL" do
gem "neeto-email-notifications-engine"
end
Run bundler to install the gem and its dependencies:
bundle install
Add required migrations in the db/migrate folder. Run the following
commands to generate the migrations.
bundle exec rails g neeto_email_notifications_engine:install
This will generate the migration to create the
neeto_email_notifications_engine_email_notifications table, which holds the
data for the email notifications, and have custom_fields column to include
custom attributes.
Apply the migrations to your database:
bundle exec rails db:migrate
Add the engine's routes to your application's config/routes.rb:
# config/routes.rb
mount NeetoEmailNotificationsEngine::Engine, at: "/neeto_email_notifications"
NOTE: The mount point & base URL must be /neeto_email_notifications and cannot be changed to any other path.
Note: The engine uses the
liquidgem for template rendering. This will be installed automatically as a dependency.
Create an initializer file config/initializers/neeto_email_notifications_engine.rb to configure the engine:
# config/initializers/neeto_email_notifications_engine.rb
NeetoEmailNotificationsEngine.configure do |config|
# IMPORTANT: Configure which model types can hold email notifications.
# This configuration is MANDATORY for the engine to work properly.
config.allowed_notification_holder_types = ["PaymentPlan", "SomeOtherModel"]
end
The allowed_notification_holder_types configuration is mandatory. Failing to configure this will result in validation errors when creating email notifications.
NeetoEmailNotificationsEngine::EmailNotification (source code)Key Associations:
belongs_to :notification_holder, polymorphic: true
has_rich_text :message
Key Validations:
notification_holder_type must be in the configured allowed_notification_holder_types.subject, message are required when is_enabled is true.send_from must be a valid email format when required.notify_emails, notify_cc_emails, notify_bcc_emails) are validated for proper email format.Available Methods:
message_body_content: Returns HTML content of the rich text message.custom_field_key: Abstract method that subclasses must implement.notification_type: Returns the notification type from custom fields.disabled_by_user?: Checks if the notification was disabled by user action.Ensure the models specified in allowed_notification_holder_types have the correct associations defined:
Single Notification Per Model (Most Common)
# app/models/form.rb
class Form < ApplicationRecord
# Standard single notification association
has_one :email_notification, as: :notification_holder,
class_name: "::NeetoEmailNotificationsEngine::EmailNotification", dependent: :destroy
# Optional: Create default notification after model creation
after_create :seed_email_notification
private
def seed_email_notification
self.create_email_notification!(
send_from: Rails.application.secrets.mailer[:default_from_email],
notify_emails: [],
is_enabled: false,
subject: "New {{form-name}} submission",
message: "A new submission has been received for {{form-name}}."
)
end
end
Multiple Notification Types Per Model
# app/models/meeting.rb
class Meeting < ApplicationRecord
# General association for all notifications
has_many :email_notifications, as: :notification_holder,
class_name: "::NeetoEmailNotificationsEngine::EmailNotification", dependent: :destroy
# Specific notification types using custom fields
has_one :reminder_notification,
-> { where("custom_fields -> 'notification_type' ? :value", value: "reminder") },
as: :notification_holder, class_name: "::NeetoEmailNotificationsEngine::EmailNotification"
has_one :confirmation_notification,
-> { where("custom_fields -> 'notification_type' ? :value", value: "confirmation") },
as: :notification_holder, class_name: "::NeetoEmailNotificationsEngine::EmailNotification"
has_one :cancellation_notification,
-> { where("custom_fields -> 'notification_type' ? :value", value: "cancellation") },
as: :notification_holder, class_name: "::NeetoEmailNotificationsEngine::EmailNotification"
after_create :setup_default_notifications
private
def setup_default_notifications
create_reminder_notification!(
send_from: "meetings@company.com",
subject: "Reminder: {{meeting-title}} starts in 1 hour",
message: "Your meeting {{meeting-title}} is scheduled to start in 1 hour.",
custom_fields: { notification_type: "reminder" },
is_enabled: false
)
create_confirmation_notification!(
send_from: "meetings@company.com",
subject: "Meeting Confirmed: {{meeting-title}}",
message: "Your meeting {{meeting-title}} has been confirmed for {{meeting-date}}.",
custom_fields: { notification_type: "confirmation" },
is_enabled: true
)
end
end
Creating Custom Notification Models
# app/models/submission_email_notification.rb
class SubmissionEmailNotification < ::NeetoEmailNotificationsEngine::EmailNotification
# Scope to only submission notifications
default_scope { where("custom_fields -> 'notification_type' ? :value", value: "submission") }
after_initialize :set_notification_type
def custom_field_key
"notification_type"
end
private
def set_notification_type
self.custom_fields ||= {}
self.custom_fields[custom_field_key] = "submission"
end
end
# Usage in host model
class Form < ApplicationRecord
has_one :submission_email_notification, as: :notification_holder, dependent: :destroy
# You can still have the general association too
has_one :email_notification, as: :notification_holder,
class_name: "::NeetoEmailNotificationsEngine::EmailNotification", dependent: :destroy
end
Database Schema Information
The engine creates a table neeto_email_notifications_engine_email_notifications with these key columns:
notification_holder_type & notification_holder_id: Polymorphic association.notify_emails: Array of recipient email addresses.notify_cc_emails & notify_bcc_emails: Arrays for CC and BCC recipients.send_from: Sender email address.subject: Email subject (supports Liquid templates).message: Rich text message content (supports Liquid templates).is_enabled: Boolean flag to enable/disable notifications.custom_fields: JSONB column for additional metadata.reply_to_id: Optional reference for reply-to configuration.type: String column for Single Table Inheritance (STI) support.Important: Host applications must define the default_attributes class method in their custom notification models that inherit from NeetoEmailNotificationsEngine::EmailNotification. This method is required and will receive the notification_holder as a parameter. This method should return a hash with the default attributes for the email notification.
Variables in the subject and message must always be wrapped like this:
<span data-variable data-label="label" data-id="key">{{key}}</span>
Example Implementation
def self.default_attributes(quiz)
{
send_from: Rails.application.secrets.mailer[:default_from_email],
notify_emails: [quiz.user.email],
is_enabled: true,
subject: "A new submission has arrived for {{quiz-name}}",
message: <<~HTML.squish
<b><span data-variable data-label="Quiz name" data-id="quiz-name">{{quiz-name}}</span></b>
has a new submission.<br/><br/>
<span data-variable data-label="All answers" data-id="all-answers">{{all-answers}}</span>
HTML
}
end
yarn add @bigbinary/neeto-email-notifications-frontend
This package will provide a single component NeetoEmailNotification, which
uses components from neeto-molecules.
If the host app doesn't already include these peer dependencies, install them:
# DO NOT INSTALL THE EXACT VERSIONS MENTIONED BELOW AS THEY MIGHT BE OUTDATED.
# ALWAYS PREFER INSTALLING THE LATEST COMPATIBLE VERSIONS.
yarn add @babel/runtime@^7.26.10 @bigbinary/neeto-cist@^1.0.17 @bigbinary/neeto-commons-frontend@^4.13.43 @bigbinary/neeto-editor@^1.47.16 @bigbinary/neeto-filters-frontend@^4.3.21 @bigbinary/neeto-icons@^1.20.49 @bigbinary/neeto-molecules@^3.16.63 @bigbinary/neetoui@^8.3.9 @honeybadger-io/js@^6.10.1 @honeybadger-io/react@^6.1.25 @tailwindcss/container-queries@^0.1.1 @tanstack/react-query@^5.59.20 @tanstack/react-query-devtools@^5.59.20 antd@^5.22.0 axios@^1.8.2 buffer@^6.0.3 classnames@^2.5.1 crypto-browserify@^3.12.1 dompurify@^3.2.4 formik@^2.4.6 https-browserify@^1.0.0 i18next@^22.5.1 js-logger@^1.6.1 mixpanel-browser@^2.47.0 os-browserify@^0.3.0 path-browserify@^1.0.1 qs@^6.11.2 ramda@^0.29.0 react@^18.3.1 react-dom@^18.3.1 react-helmet@^6.1.0 react-i18next@^12.3.1 react-router-dom@^5.3.3 react-toastify@^8.0.2 source-map-loader@^4.0.1 stream-browserify@^3.0.0 stream-http@^3.2.0 tailwindcss@^3.4.14 tty-browserify@^0.0.1 url@^0.11.0 util@^0.12.5 vm-browserify@^1.1.2 yup@^0.32.11 zustand@^4.4.2
Note: Carefully manage potential version conflicts with your host application.
NeetoEmailNotificationForm (source code)Props
| Prop | Type | Default | Description |
|---|---|---|---|
emailNotificationParams | Object | {} | Required. Parameters for fetching email notification data |
title | String | "Email notification" | Title displayed above the notification toggle |
notificationToggleLabel | String | "Send an email notification when a new event occurred" | The label displayed beside the notification toggle switch |
disabled | Boolean | false | Disables the entire component |
onSuccess | Function | noop | Callback function triggered after successful notification update |
breadcrumbs | Array | [] | Breadcrumb navigation data |
children | ReactNode | undefined | Additional content rendered when notifications are enabled |
blockNavigation | Boolean | false | Shows block navigation alert for unsaved changes |
helpPopoverProps | Object | {} | Props for the help popover component |
tooltipProps | Object | {} | Props for tooltip shown when component is disabled |
emailFormProps | Object | {} | Props passed to the underlying EmailForm component |
emailFormikProps | Object | {} | Props passed to the EmailFormProvider component |
emailPreviewProps | Object | {} | Props passed to the EmailPreview component |
fieldsVisibility | Object | {} | Controls which fields are visible in the email form |
Default visibility for each field is as follows:
{
showSendToField: true,
showReplyToField: false,
showSendToAsRadio: false,
showCcField: false,
showBccField: false,
}
You can override any of these by passing a fieldsVisibility prop with your
desired values.
emailNotificationParams Object Structure
{
notificationHolderId: "uuid-string", // ID of the notification holder
notificationHolderType: "Form", // Type of the notification holder
customFields: { // Optional custom fields for filtering
notificationType: "submission" // Example: different notification types
}
}
Usage Example
import React from "react";
import { NeetoEmailNotificationForm } from "@bigbinary/neeto-email-notifications-frontend";
const FormSettingsPage = ({ formId }) => {
const handleNotificationUpdate = () => {
console.log("Email notification updated successfully!");
};
return (
<NeetoEmailNotificationForm
title="Form Submission Notification"
notificationToggleLabel="Get notified when someone submits your form"
emailNotificationParams={{
notificationHolderId: formId,
notificationHolderType: "Form",
customFields: { notificationType: "submission" }
}}
emailPreviewProps={{
formatBody: message => replaceVariablesWithDummyValues(message, values),
}}
breadcrumbs={[
{ text: "Forms", link: "/forms" },
{ text: "Settings", link: `/forms/${formId}/settings` }
]}
onSuccess={handleNotificationUpdate}
/>
);
};
export default FormSettingsPage;
useFetchEmailNotifications (source code)Fetches email notification data for a specific notification holder.
import { useFetchEmailNotifications } from "@bigbinary/neeto-email-notifications-frontend";
const { data, isLoading, error } = useFetchEmailNotifications({
notificationHolderId: "form-uuid",
notificationHolderType: "Form",
customFields: { notificationType: "submission" }
});
useUpdateEmailNotification (source code)Updates email notification settings.
import { useUpdateEmailNotification } from "@bigbinary/neeto-email-notifications-frontend";
const { mutate: updateEmailNotification, isPending } = useUpdateEmailNotification();
const handleUpdate = (notificationData) => {
updateEmailNotification({
...notificationData,
notificationHolderId: "form-uuid",
notificationHolderType: "Form"
});
};
You can create specialized notification models that inherit from the base EmailNotification class:
class SubmissionEmailNotification < ::NeetoEmailNotificationsEngine::EmailNotification
default_scope { where("custom_fields -> 'notification_type' ? :value", value: "submission") }
after_initialize :set_notification_type
def custom_field_key
"notification_type"
end
private
def set_notification_type
self.custom_fields ||= {}
self.custom_fields[custom_field_key] = "submission"
end
end
Configure your models to support email notifications:
class Meeting < ApplicationRecord
has_one :reminder_notification, -> { where("custom_fields -> 'notification_type' ? :value", value: "reminder") },
as: :notification_holder, class_name: "::NeetoEmailNotificationsEngine::EmailNotification"
has_one :confirmation_notification, -> { where("custom_fields -> 'notification_type' ? :value", value: "confirmation") },
as: :notification_holder, class_name: "::NeetoEmailNotificationsEngine::EmailNotification"
after_create :setup_notifications
private
def setup_notifications
create_reminder_notification!(
send_from: "meetings@company.com",
subject: "Reminder: {{meeting-title}} in 1 hour",
message: "Your meeting {{meeting-title}} is scheduled to start in 1 hour.",
custom_fields: { notification_type: "reminder" }
)
create_confirmation_notification!(
send_from: "meetings@company.com",
subject: "Meeting Confirmed: {{meeting-title}}",
message: "Your meeting {{meeting-title}} has been confirmed for {{meeting-date}}.",
custom_fields: { notification_type: "confirmation" }
)
end
end
It is recommended to automatically create a default email notification record for each instance of your model. This ensures the notification UI and API always have a record to fetch and update, preventing errors and missing functionality. You can use an after_create callback in your model to seed this record.
class Quiz < ApplicationRecord
has_many :email_notifications, as: :notification_holder,
class_name: "NeetoEmailNotificationsEngine::EmailNotification", dependent: :destroy
has_one :push_email_notification, as: :notification_holder
after_create :create_default_email_notification
private
def create_default_email_notification
self.create_push_email_notification!(PushEmailNotification.default_attributes(self))
end
end
Create service classes that include the email notification functionality:
class MeetingReminderService
include ::NeetoEmailNotificationsEngine::EmailNotificationService
def initialize(meeting)
@meeting = meeting
@email_notification = meeting.reminder_notification
end
private
def send_emails
return unless @email_notification.is_enabled?
MeetingMailer.reminder_email(
recipients: @email_notification.notify_emails,
cc: @email_notification.notify_cc_emails,
bcc: @email_notification.notify_bcc_emails,
subject: @subject,
message: @message,
meeting: @meeting
).deliver_now
end
def load_liquid_parameters
@liquid_parameters[:text] = {
"meeting-title" => @meeting.title,
"meeting-date" => @meeting.scheduled_at.strftime("%B %d, %Y"),
"meeting-time" => @meeting.scheduled_at.strftime("%I:%M %p")
}
@liquid_parameters[:html] = @liquid_parameters[:text]
end
end
# Usage
meeting = Meeting.find(params[:id])
MeetingReminderService.new(meeting).process
The engine exposes API endpoints under the configured mount path (default /neeto_email_notifications):
| Method | Path | Description | Parameters |
|---|---|---|---|
| GET | /email_notification | Fetch email notification settings | notification_holder_id, notification_holder_type, custom_fields |
| PUT | /email_notification | Update email notification settings | notification_holder_id, notification_holder_type, email_notification params |
Example API Usage:
// Fetch notification settings
axios.get('/neeto_email_notifications/email_notification', {
params: {
notification_holder_id: 'form-uuid',
notification_holder_type: 'Form',
custom_fields: { notification_type: 'submission' }
}
})
// Update notification settings
axios.put('/neeto_email_notifications/email_notification', {
notification_holder_id: 'form-uuid',
notification_holder_type: 'Form',
email_notification: {
is_enabled: true,
subject: 'New form submission',
message: 'A new submission was received.',
notify_emails: ['admin@company.com'],
send_from: 'forms@company.com'
}
})
Email subjects and messages support Liquid templating for dynamic content:
# In your notification setup
email_notification.update!(
subject: "New {{form-name}} submission from {{user-name}}",
message: "Hello {{admin-name}}, a new submission was received for {{form-name}} on {{submission-date}}."
)
# In your service class
def load_liquid_parameters
@liquid_parameters[:text] = {
"form-name" => @form.name,
"user-name" => @submission.user.name,
"admin-name" => @form.owner.name,
"submission-date" => @submission.created_at.strftime("%B %d, %Y")
}
@liquid_parameters[:html] = @liquid_parameters[:text]
end
Check the Frontend package development guide for step-by-step instructions to develop the frontend package.
Rails Server: Start the main application
bundle exec rails server
Database Setup: Ensure migrations are run
bundle exec rails db:migrate
Testing: Run the test suite
bundle exec rails test
The engine provides factories for testing:
# Use in your tests
FactoryBot.create(:neeto_email_notification_engine_email_notification,
notification_holder: your_model_instance
)
Use the test/dummy app within the engine's repository for isolated testing.
For instructions on building and releasing the @bigbinary/neeto-email-notifications-frontend NPM package and the neeto-email-notifications-engine Ruby gem, please refer to the internal guide: Building and Releasing Packages.
FAQs
A repo acts as the source of truth for the new nano's structure, configs, data etc.
We found that @bigbinary/neeto-email-notifications-frontend demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Socket CTO Ahmad Nassri discusses why supply chain attacks now target developer machines and what AI means for the future of enterprise security.

Security News
Learn the essential steps every developer should take to stay secure on npm and reduce exposure to supply chain attacks.

Security News
Experts push back on new claims about AI-driven ransomware, warning that hype and sponsored research are distorting how the threat is understood.