Skip to contents

Overview

This guide walks through common email workflows in the Artalytics platform using artsend. Each section provides complete, copy-paste-ready examples.

Prerequisites

library(artsend)

# Verify configuration
if (!is_resend_configured()) {
  stop("Set ART_RESEND_KEY environment variable first")
}

Artists receive messages from visitors viewing their gallery. The email includes visitor info, message content, and optional artwork context.

Basic Contact Email

result <- send_contact_email(
  to = "artist@example.com",
  visitor_name = "Sarah Johnson",
  visitor_email = "sarah@collector.com",
  msg = "Your piece 'Urban Dreams' resonates deeply with me.
             I'd love to discuss acquisition possibilities."
)

if (result$success) {
  message("Contact email sent! Resend ID: ", result$message_id)
  # Log to database, show success message, etc.
} else {
  warning("Email failed: ", result$error)
  # Retry logic, alert admin, etc.
}

Contact Email with Artwork Context

Include artwork details to provide context:

result <- send_contact_email(
  to = "artist@example.com",
  visitor_name = "Sarah Johnson",
  visitor_email = "sarah@collector.com",
  msg = "I'm interested in purchasing this piece.",
  art_title = "Urban Dreams #42",
  art_url = "https://cdn.artalytics.app/artworks/abc123/thumb.jpg"
)

The email will display the artwork thumbnail and title, helping the artist remember which piece sparked the conversation.

Custom Subject Line

Override the default auto-generated subject:

result <- send_contact_email(
  to = "artist@example.com",
  visitor_name = "Sarah Johnson",
  visitor_email = "sarah@collector.com",
  msg = "Commission inquiry for corporate lobby installation.",
  subject = "Commission Inquiry - Corporate Installation"
)

Custom Sender Address

Use a different sender email (must be verified in Resend):

result <- send_contact_email(
  to = "artist@example.com",
  visitor_name = "Sarah Johnson",
  visitor_email = "sarah@collector.com",
  msg = "Your artwork would be perfect for our upcoming exhibition.",
  from = "gallery@artalytics.app"
)

Pilot Program Workflow

Artists join the Artalytics pilot program through a two-step email workflow: waitlist confirmation, then invitation when accepted.

Step 1: Waitlist Confirmation

Send immediately when artist submits application:

# After creating waitlist record in database
waitlist_id <- "wl-a7b3c2d1"

result <- send_waitlist_confirm(
  to = "newartist@example.com",
  artist_name = "Marcus Chen",
  waitlist_id = waitlist_id
)

if (result$success) {
  # Update database with confirmation sent timestamp
  data.table::setDT(waitlist_records)[
    id == waitlist_id,
    confirmation_sent_utc := lubridate::now("UTC")
  ]
}

Step 2: Send Invitation

When admin approves artist (status: pending → invited):

result <- send_artist_invite(
  to = "newartist@example.com",
  artist_name = "Marcus Chen",
  onboard_url = "https://artalytics.app/onboarding?token=xyz789"
)

if (result$success) {
  # Update database status
  data.table::setDT(waitlist_records)[
    email == "newartist@example.com",
    `:=`(
      status = "invited",
      invited_utc = lubridate::now("UTC"),
      invitation_id = result$message_id
    )
  ]
}

Whitepaper Delivery

Send whitepapers with personalized content based on user type.

Send to Investor

result <- send_wp_email(
  to = "partner@vcfirm.com",
  usr_type = "investor"
)

The email includes investment-focused messaging, market size, and traction metrics.

Send to Artist

result <- send_wp_email(
  to = "artist@example.com",
  usr_type = "artist"
)

The email emphasizes platform benefits for artists, analytics features, and gallery tools.

Send to General Audience

result <- send_wp_email(
  to = "info@collector.com",
  usr_type = "other"
)

Generic messaging suitable for collectors, press, or other stakeholders.

Custom Whitepaper URL

Override the default whitepaper URL:

result <- send_wp_email(
  to = "investor@fund.com",
  usr_type = "investor",
  wp_url = "https://cdn.artalytics.app/docs/whitepaper-v2.1.pdf"
)

Investor Welcome Package

For qualified investors, send a comprehensive welcome email with optional data room access.

Basic Investor Welcome

result <- send_investor_welcome(
  to = "partner@vcfirm.com",
  investor_name = "Jennifer Martinez",
  incl_dataroom = FALSE
)

With Data Room Access

result <- send_investor_welcome(
  to = "partner@a16z.com",
  investor_name = "Partner Name",
  incl_dataroom = TRUE
)

The email includes:

  • Market opportunity overview
  • Key traction metrics
  • Whitepaper download link
  • Data room access (if enabled)
  • Calendar scheduling link

Error Handling Patterns

Validation Before Sending

# Validate email format first
visitor_email <- "user-input@example.com"

if (!validate_email_fmt(visitor_email)) {
  stop("Invalid email address provided")
}

# Proceed with sending
result <- send_contact_email(...)

Retry Logic

send_with_retry <- function(..., max_attempts = 3) {
  for (attempt in seq_len(max_attempts)) {
    result <- send_contact_email(...)

    if (result$success) {
      return(result)
    }

    if (attempt < max_attempts) {
      Sys.sleep(2^attempt)  # Exponential backoff
    }
  }

  result  # Return final failed result
}

Logging

result <- send_contact_email(...)

if (result$success) {
  rdstools::log_inf("Email sent successfully: {result$message_id}")
} else {
  rdstools::log_err("Email failed: {result$error}")
}

Integration with Database

Common pattern for tracking sent emails:

library(data.table)

# Create email log record
email_log <- data.table(
  email_id = uuid::UUIDgenerate(),
  recipient = "artist@example.com",
  email_type = "contact_form",
  sent_utc = lubridate::now("UTC"),
  resend_id = NA_character_,
  success = FALSE,
  error_msg = NA_character_
)

# Send email
result <- send_contact_email(
  to = email_log$recipient,
  visitor_name = "John Doe",
  visitor_email = "john@example.com",
  msg = "Great artwork!"
)

# Update log record
email_log[, `:=`(
  resend_id = if (result$success) result$message_id else NA_character_,
  success = result$success,
  error_msg = if (!result$success) result$error else NA_character_
)]

# Insert to database
# artcore::dbc() |> DBI::dbAppendTable("email_log", email_log)

Environment-Specific Configuration

Development

# Use test API key
Sys.setenv(ART_RESEND_KEY = "re_test_xxxxxxxxxxxxx")

# Send to test recipients only
dev_mode <- Sys.getenv("ART_ENV") == "development"

recipient <- if (dev_mode) {
  "dev-test@artalytics.app"
} else {
  artist_email
}

result <- send_contact_email(to = recipient, ...)

Production

# Verify production API key is set
stopifnot(
  Sys.getenv("ART_RESEND_KEY") != "",
  stringr::str_detect(Sys.getenv("ART_RESEND_KEY"), "^re_")
)

# Send to real recipients
result <- send_contact_email(
  to = artist_email,
  ...
)

Next Steps

Common Issues

API key not found
Set ART_RESEND_KEY environment variable. Add to .Renviron for persistence.
Email not delivered
Check Resend dashboard for delivery status. Verify recipient email is valid. Check spam folders.
Invalid email format
Use validate_email_fmt() to check emails before sending.
Rate limiting
Resend free tier: 100 emails/day. Upgrade plan if needed. Implement retry with exponential backoff.