PHP — один из самых популярных серверных скриптовых языков, и не без причины. Он универсален, прост в использовании и легко интегрируется с базами данных вроде MySQL, что делает его отличным выбором для создания динамических сайтов. К тому же, благодаря открытому исходному коду PHP обеспечивает гибкость и экономичность при работе над проектами любого масштаба.
Что касается работы с электронной почтой, это критически важный функционал для многих веб-приложений. От регистрации пользователей и сброса паролей до уведомлений и маркетинговых кампаний — письма играют большую роль в веб-разработке. В этом как раз и помогает Testmail: он позволяет протестировать ваши почтовые сценарии и убедиться, что всё работает без сбоев, прежде чем письма попадут во входящие ваших клиентов.
В этом руководстве мы пошагово разберём, как получать письма в почтовый ящик Testmail и использовать Testmail API для выполнения запросов к входящим — и всё это с помощью PHP. Давайте приступим!
Предварительные требования
Установка PHP: убедитесь, что PHP установлен на вашем локальном сервере или в среде хостинга. Вы можете скачать последнюю версию с официального сайта PHP или использовать среду разработки, такую как XAMPP, WAMP или Laragon, в которых PHP уже предустановлен и настроен для удобства работы.
Учётная запись testmail.app: зарегистрируйте бесплатный аккаунт на testmail.app и получите ваш API-ключ и namespace. Это позволит вам использовать API testmail.app для выполнения запросов и программного тестирования писем.
Вам также понадобится текстовый редактор или IDE для написания кода и управления им.
Настройка проекта
Создайте новую директорию для вашего проекта: откройте терминал или командную строку и выполните следующие команды, чтобы создать новую директорию и перейти в неё. В этом примере мы используем email-tests в качестве имени директории.
mkdir email-tests
cd email-tests Инициализируйте новый проект Composer. Если у вас не установлен Composer, вы можете скачать его здесь. Следуйте подсказкам или нажмите Enter, чтобы использовать настройки по умолчанию.
composer init Testmail предоставляет два API: простой JSON API и более продвинутый GraphQL API. В этом руководстве мы сосредоточимся на GraphQL API (подробнее см.: Выбор API).

Для взаимодействия с GraphQL API вам понадобится специализированный GraphQL-клиент (рекомендуется) или обычный HTTP-клиент. В этом руководстве мы будем использовать GraphQL API вместе с библиотекой Softonic/graphql-client, но вы можете выбрать любой другой клиент по желанию.
composer require softonic/graphql-client Вы также можете использовать любой другой GraphQL-клиент на ваш выбор. Список альтернативных GraphQL-клиентов можно найти здесь.
Настройка GraphQL-клиента в PHP
Теперь, когда вы настроили проект Composer и установили необходимую библиотеку, можно перейти к настройке PHP. На этом этапе вы подключитесь к GraphQL API Testmail с помощью вашего API-ключа.
<?php
// Autoload Composer packages
require __DIR__ . '/vendor/autoload.php';
// Import the GraphQL client library
use Softonic\GraphQL\ClientBuilder;
// Replace 'YOUR_APIKEY' with your API key
$APIKEY = 'YOUR_APIKEY';
// Set up the GraphQL client with your API endpoint and authorization header
$client = ClientBuilder::build(
'https://api.testmail.app/api/graphql', // Testmail GraphQL endpoint
[
'headers' => ['Authorization' => "Bearer $APIKEY"] // Authorization header with API key
]
); Отправка тестового письма
Вы можете инициировать отправку письма с помощью пользовательской функции (например, при нажатии кнопки регистрации) или просто отправить письмо через ваш привычный почтовый клиент (например, Gmail, Outlook) на ваш адрес testmail.app: {namespace}.{tag}@inbox.testmail.app .
Вот как это работает:
- Namespace: Представьте ваш namespace как коллекцию почтовых ящиков. Каждый namespace уникален для вас и может содержать неограниченное количество email-адресов. Вы можете найти ваш уникальный namespace в консоли Testmail.
- Tag: Тег вы задаёте сами. Используя разные теги, вы можете мгновенно создавать новые email-адреса и почтовые ящики.
Например, допустим, ваш namespace — acmeinc . Если вы отправите тестовое письмо на [email protected] , а другое на [email protected] , оба письма попадут в namespace acmeinc .
Поиск письма
Теперь, когда у нас есть письмо для тестирования, давайте найдем его по теме. Запрос, который мы будем использовать, — это inbox , он извлекает письма из указанного namespace. Он принимает один обязательный аргумент: namespace. Вместе с деталями письма запрос вернёт result (значение success или fail ) и message (с объяснением причины в случае ошибки).
Создайте новый файл, например check_email.php , внутри папки email-tests . Давайте выполним запрос к входящим для поиска письма по теме.
<?php
require __DIR__ . '/vendor/autoload.php';
use Softonic\GraphQL\ClientBuilder;
$APIKEY = 'YOUR_APIKEY'; // Replace with your API key
$NAMESPACE = 'YOUR_NAMESPACE'; // Replace with your namespace
$SUBJECT = 'Testmail PHP Integration'; // Replace with the subject you're looking for
$client = ClientBuilder::build(
'https://api.testmail.app/api/graphql',
['headers' => ['Authorization' => "Bearer $APIKEY"]]
);
// GraphQL query to get emails from the inbox
$query = <<<QUERY
{
inbox(namespace: "$NAMESPACE") {
emails {
subject
}
}
}
QUERY;
$response = $client->query($query);
$emails = $response->getData()['inbox']['emails'];
foreach ($emails as $email) {
if ($email['subject'] === $SUBJECT) {
echo "Email with subject '$SUBJECT' found.\n";
exit;
}
}
echo "Email with subject '$SUBJECT' not found.\n"; check_email.php
Запустите скрипт:
php check_email.php Вывод должен показать, было ли найдено письмо с указанной темой во входящих.
Использование «живого» (Live) запроса
Когда вы ожидаете получения письма, вместо регулярных повторных запросов к входящим в цикле вы можете использовать live-запрос. Live-запрос ждёт, пока хотя бы одно письмо не совпадёт с условиями, и только затем возвращает ответ. Это гораздо эффективнее, чем постоянный опрос (polling) почтового ящика.
Например, ваш запрос можно изменить следующим образом:
$query = <<<'QUERY'
query GetMails {
inbox (
namespace:"YOUR_NAMESPACE"
livequery:true
) {
result
message
emails {
subject
}
}
}
QUERY; Когда вы отправляете live-запрос, API начинает ожидать новые письма, соответствующие вашему запросу. Как только подпадающее под условия письмо поступает, API мгновенно возвращает результат. Если в течение минуты письмо не найдено, API отправляет HTTP 307 редирект, побуждая ваш клиент повторить тот же запрос. Этот процесс продолжается неограниченно долго, поэтому важно настроить таймаут в вашем тестовом окружении, чтобы запрос не выполнялся бесконечно.
Уточнение поиска
GraphQL API предоставляет отличные возможности для сортировки и фильтрации писем. Полное справочное руководство по GraphQL API доступно в GraphQL playground (см. всплывающие панели schema и docs справа).
Вы можете настраивать запрос к входящим на основе нескольких параметров, чтобы фильтровать и сортировать письма различными способами. В таблице ниже описан каждый параметр, его описание и пример использования.
| Параметр | Описание | Пример использования |
|---|---|---|
namespace |
Уникальный идентификатор вашего namespace почтового ящика. Письма отправляются на {namespace}.{tag}@inbox.testmail.app . Для доступа к этому namespace вам понадобятся права авторизованного API-ключа. |
namespace: "myapp" |
tag |
Фильтрует письма на основе вашего пользовательского тега. Теги помогают создавать отдельные почтовые ящики внутри одного namespace. | tag: "john" |
tag_prefix |
Фильтрует письма по началу тега. Например, tag_prefix: "john" совпадёт с письмами, отправленными на "john", "john.smith" и т. д. |
tag_prefix: "john" |
timestamp_from |
Извлекает письма, полученные после указанной временной метки (в миллисекундах с 1 января 1970 года). | timestamp_from: 1621280000000 |
timestamp_to |
Извлекает письма, полученные до указанной временной метки. Этот параметр игнорируется, если livequery равен true. |
timestamp_to: 1621283600000 |
advanced_filters |
Позволяет выполнять расширенную фильтрацию по конкретным полям (например, subject, from, text). Также может включать поиск с использованием подстановочных знаков (wildcards). | [{ field: "subject", match: "exact", value: "Test Email" }] |
advanced_sorts |
Определяет порядок сортировки результатов. Допускается указание нескольких правил сортировки, при этом их порядок имеет значение. | [{ field: "timestamp", order: "desc" }, { field: "subject", order: "asc" }] |
livequery |
Если true, сервер ждёт поступления подходящего письма во входящие перед отправкой ответа. Полезно для тестирования писем в реальном времени. | livequery: true |
limit |
Задаёт максимальное количество извлекаемых писем. Полезно для пагинации или ограничения результатов. | limit: 5 |
offset |
Задаёт количество писем, которое нужно пропустить. Полезно для пагинации начиная с определённой позиции. | offset: 10 |
Расширенные фильтры (Advanced Filters) помогают сузить поиск по конкретным деталям письма, а расширенные сортировки (Advanced Sorts) позволяют упорядочить результаты по различным полям.
| Поле | Расширенный фильтр | Расширенная сортировка |
|---|---|---|
| tag | ✔ | ✔ |
| envelope_from | ✔ | ✔ |
| envelope_to | ✔ | ✔ |
| from | ✔ | ✔ |
| to | ✔ | ✔ |
| cc | ✔ | ✔ |
| subject | ✔ | ✔ |
| text | ✔ | ✘ |
| html | ✔ | ✘ |
| sender_ip | ✔ | ✔ |
| id | ✔ | ✘ |
| timestamp | ✘ | ✔ |
| spam_score | ✘ | ✔ |
Пример: приведенный ниже скрипт фильтрует письма, указывая namespace и префикс тега, например "peter", чтобы включить только те письма, которые начинаются с данного тега. Он также применяет расширенный фильтр для поиска писем с точным совпадением темы, например "Please confirm your email". Затем результаты сортируются в два этапа: сначала по тегу в алфавитном порядке по возрастанию, а затем по временной метке по убыванию.
$query = <<<QUERY
{
inbox (
namespace:"YOUR_NAMESPACE"
tag_prefix:"peter"
advanced_filters:[{
field:subject
match:exact
action:include
value:"Please confirm your email"
}]
advanced_sorts:[{
field:tag,
order:asc
}, {
field:timestamp,
order:desc
}]
) {
result
message
count
emails {
tag
timestamp
}
}
}
QUERY;
$variables = [];
$response = $client->query($query, $variables);
$r = $response->getData();
echo "<pre>".json_encode($r, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)."</pre>";
?> Чтобы использовать запрос с подстановочными знаками, вы можете установить для поля match значение wildcard . Это позволит вам искать шаблоны в таких полях, как тема или HTML-тело письма, с помощью подстановочных знаков * (соответствует любому количеству символов) и ? (соответствует одному символу).
Обратите внимание, что параметры timestamp_from , timestamp_to , tag и tag_prefix являются наиболее эффективными способами фильтрации писем. Теги индексируются с использованием n-грамм — поэтому запросы по тегам и подмножествам тегов выполняются невероятно быстро. Вот типичный паттерн использования, который этим пользуется:
Отправляйте письма на: [email protected] (где тег равен category.subcategory ), а затем запрашивайте письма, используя tag_prefix:
-
tag_prefix:"category"вернёт все письма, относящиеся к этой категории -
tag_prefix:"category.subcategory"вернёт все письма, относящиеся к этой категории и подкатегории - (и так далее)
Такое вложение тегов позволяет группировать/категоризировать входящие сообщения, уменьшать конфликты и реже использовать advanced_filters (которые работают менее производительно).
По умолчанию письма сортируются по timestamp в порядке убывания (сначала самые новые), но вы можете изменить это поведение с помощью advanced_sorts для более точного контроля.
Если вы запускаете несколько тестов или работаете в параллельных пайплайнах CI, убедитесь, что ваши фильтры достаточно специфичны. Без надлежащей фильтрации live-запрос может вернуть любое новое письмо, что приведёт к непредсказуемым результатам. Например, если вы проверяете наличие письма с <h1>Getting started</h1> , вы можете использовать фильтр с подстановочным знаком для поля html и запрашивать только количество совпавших писем, избегая необходимости скачивать весь контент.
Проверка проблем со спамом
Как правило, вам не нужно беспокоиться о спам-фильтрах, если:
- Ваши письма действительно релевантны и не содержат спама.
- Вы правильно настроили DKIM и SPF.
- Ваш домен, почтовые серверы и IP-адреса имеют хорошую репутацию (не находятся в чёрных списках).
Testmail использует SpamAssassin — популярную антиспам-платформу с открытым исходным кодом — для проверки писем на спам. Оценки спама и отчёты, генерируемые SpamAssassin, не являются универсальными, так как они зависят от конкретных наборов правил и плагинов, включённых у каждого почтового провайдера. Разные провайдеры могут настраивать свои системы с уникальными правилами и порогами срабатывания, поэтому классификация спама может отличаться у разных сервисов.
Вы также можете проверить, проходит ли письмо проверки Sender Policy Framework (SPF) и DomainKeys Identified Mail (DKIM). Проверки SPF и DKIM помогают убедиться, что письмо действительно отправлено заявленным отправителем. SPF проверяет, что письмо пришло с разрешённого сервера, а DKIM проверяет, не изменялось ли содержимое письма. Эти проверки помогают защититься от поддельных или мошеннических писем.
$query = <<<QUERY
{
inbox (
namespace: "YOUR_NAMESPACE"
tag_prefix: "YOUR_TAG"
spam_report: true # Requesting spam report for the emails
) {
result
message
count
emails {
tag
spam_score # Including spam score
spam_report # Including spam report details
spf # SPF authentication status
dkim # DKIM authentication status
}
}
}
QUERY;
Коротко о главном (TL;DR)
- Не беспокойтесь о баллах спама (spam score) ниже 5.
- Если балл спама превышает 5: посмотрите, какие правила сработали в spam_report, и устраните наиболее критичные проблемы.
- Отрицательные баллы спама возможны (и это хорошо).
SPF и DKIM
Вы также можете проверить, проходит ли письмо проверки Sender Policy Framework (SPF) и DomainKeys Identified Mail (DKIM). spf и dkim необходимы для проверки подлинности письма и гарантируют, что оно действительно отправлено заявленным отправителем.
SPF — это механизм, который гарантирует, что письмо пришло с разрешённого сервера, усложняя злоумышленникам отправку писем от чужого имени. DKIM, с другой стороны, фокусируется на самом содержимом письма. Он подлинность того, что письмо не было изменено при передаче, добавляя цифровую подпись в заголовок. Эту подпись можно проверить с помощью публичного ключа, чтобы убедиться в неизменности контента.
Тестирование текстового и HTML-содержимого письма
Тестирование текстового и HTML-контента в письмах крайне важно для проверки точности и корректности сообщений. Используя расширенные фильтры для поиска конкретных ключевых слов или шаблонов в теле письма, вы можете убедиться, что письма содержат нужную информацию и соответствуют вашим критериям тестирования.
Вы можете фильтровать письма по текстовому содержимому с помощью поля text с совпадением wildcard (* и ?) для нечёткого поиска или exact для точных совпадений.
$query = <<<QUERY
{
inbox(
namespace: "YOUR_NAMESPACE"
tag: "YOUR_TAG"
advanced_filters: [
{
field: text
match: wildcard
action: include
value: "*specific keyword*"
}
]
limit: 10
offset: 0
) {
result
message
count
emails {
id
namespace
tag
timestamp
subject
from
text # Access the text content here
}
}
}
QUERY; text или html ) превышает 30 КБ, оно не будет проиндексировано для расширенного поиска, поэтому вы не сможете использовать его в фильтрах для таких больших писем. Если вам нужен полнотекстовый поиск по большим письмам, пожалуйста, свяжитесь с нами.Извлечение OTP-кодов и ссылок из письма
Тестирование сценариев с отправкой одноразовых паролей (OTP) по email — ключевая часть проверки регистраций, входов и сбросов паролей. Если OTP-код отсутствует, неверен или его трудно извлечь, пользователи сразу же сталкиваются с проблемой.
При тестировании доставки OTP по электронной почте обычно нужно убедиться в следующем:
- Письмо с OTP получено
- OTP-код успешно извлекается из письма
- Код совпадает с тем, который ожидает ваше приложение
Получив текстовое или HTML-содержимое письма, вы можете извлечь из него специфические шаблоны — например, OTP-коды или ссылки — с помощью регулярных выражений (regex). Большинство OTP-кодов представляют собой короткие числовые или буквенно-цифровые последовательности (например, 6-значные коды), что облегчает их поиск.
<?php
require __DIR__ . '/vendor/autoload.php';
use Softonic\GraphQL\ClientBuilder;
$APIKEY = 'YOUR_APIKEY';
$NAMESPACE = 'YOUR_NAMESPACE';
$TAG = 'YOUR_TAG';
$client = ClientBuilder::build(
'https://api.testmail.app/api/graphql',
['headers' => ['Authorization' => "Bearer $APIKEY"]]
);
$query = <<<QUERY
{
inbox(
namespace: "$NAMESPACE"
tag: "$TAG"
) {
emails {
subject
text
}
}
}
QUERY;
$response = $client->query($query);
$emails = $response->getData()['inbox']['emails'];
foreach ($emails as $email) {
echo "Subject: " . $email['subject'] . "\n";
// Extract 6-digit code
if (preg_match('/\b\d{6}\b/', $email['text'], $matches)) {
echo "Code found: " . $matches[0] . "\n";
} else {
echo "No code found.\n";
}
}
?> Вы можете использовать это для автоматизации тестирования email OTP, валидации сценариев входа или регистрации, а также для запуска end-to-end тестов, зависящих от подтверждения по почте.
Помимо OTP, многие письма содержат ссылки (например, для подтверждения аккаунта или сброса пароля). Их также следует протестировать, чтобы убедиться в их валидности и доступности.
В примере ниже ссылки извлекаются из содержимого письма и проверяется их HTTP-статус с помощью curl
<?php
require __DIR__ . '/vendor/autoload.php';
use Softonic\GraphQL\ClientBuilder;
$APIKEY = 'YOUR_APIKEY';
$NAMESPACE = 'YOUR_NAMESPACE';
$TAG = 'YOUR_TAG';
$client = ClientBuilder::build(
'https://api.testmail.app/api/graphql',
['headers' => ['Authorization' => "Bearer $APIKEY"]]
);
$query = <<<QUERY
{
inbox(
namespace: "$NAMESPACE"
tag: "$TAG"
) {
emails {
subject
text # Access the text content here
}
}
}
QUERY;
$response = $client->query($query);
$emails = $response->getData()['inbox']['emails'];
// Function to check if a URL is reachable
function checkUrl($url) {
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_NOBODY, true);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 10);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_exec($curl);
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
return $httpCode >= 200 && $httpCode < 400; // 2xx and 3xx are considered valid
}
foreach ($emails as $email) {
echo "Email Subject: " . $email['subject'] . "\n";
echo "Email Text Content: " . $email['text'] . "\n";
// Extract links using a regex pattern
if (preg_match_all('/https?:\/\/[^\s]+/', $email['text'], $matches)) {
$links = $matches[0];
echo "Found Links:\n";
foreach ($links as $link) {
echo "- $link\n";
// Check if the link is working
if (checkUrl($link)) {
echo "Link is working\n";
} else {
echo "Link is not working\n";
}
}
} else {
echo "No links found in the email text.\n";
}
} При извлечении URL-адресов из контента регулярное выражение должно быть достаточно гибким, чтобы обрабатывать различные форматы URL.
preg_match_all('/https?:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/', $htmlContent, $matches); Тестирование вложений
Будь то проверка формата (например, PDF, изображений или документов) или подтверждение того, что файл открывается без проблем, тестирование вложений помогает убедиться в корректной работе ваших писем. Это может быть особенно важно для приложений, работающих с выставлением счетов, рассылками или любыми сервисами, где прикреплённые документы играют ключевую роль.
Объект Attachment возвращает всю доступную информацию о вложениях в письме. Вы можете определить тип файла (например, изображение, PDF или документ) на основе contentType.
query {
inbox(namespace: "YOUR_NAMESPACE" tag: "YOUR_TAG") {
emails {
attachments {
filename
contentType
checksum
size
headers {
name
value
}
downloadUrl
contentId
cid
related
}
}
}
} При работе с вложениями почты MD5 checksum является полезным инструментом для проверки целостности файла. Он генерирует уникальный хэш контента, помогая вам убедиться, что файл не был изменён или повреждён.
Параметр downloadUrl отлично подходит для прямого доступа к вложению, позволяя легко скачать его. В то же время contentId или cid служат идентификаторами встроенных изображений внутри письма, позволяя ссылаться на них или работать с ними по мере необходимости.
Если для поля related установлено значение true , это указывает на то, что вложение представляет собой встроенный контент, а не отдельный файл. Это означает, что оно является частью ресурсов письма, как, например, изображение, встроенное непосредственно в тело самого письма.
Тестирование изображений и веб-маяков
Если изображение не загружается или отображается некорректно, это может испортить впечатление от письма и снизить его эффективность. Тестируя встроенные изображения, вы можете убедиться, что на них созданы правильные ссылки, они отображаются так, как задумывалось, и сохраняют стабильное визуальное качество в различных почтовых клиентах.
Встроенные изображения в электронных письмах часто ссылаются с помощью URL-адресов cid: (Content-ID). Эти изображения обычно представляют собой встроенные (inline) вложения, которые конвертируются в формат base64 для внедрения в письмо. В HTML-теле письма URL-адрес cid: будет находиться в атрибутах src тегов <img> , и такие изображения будут встроены непосредственно в письмо.
Извлечение изображений cid: из HTML
<?php
require __DIR__ . '/vendor/autoload.php';
use Softonic\GraphQL\ClientBuilder;
$APIKEY = 'YOUR_APIKEY';
$NAMESPACE = 'YOUR_NAMESPACE';
$TAG = 'YOUR_TAG';
$client = ClientBuilder::build(
'https://api.testmail.app/api/graphql',
['headers' => ['Authorization' => "Bearer $APIKEY"]]
);
$query = <<<QUERY
{
inbox(
namespace: "$NAMESPACE"
tag: "$TAG"
) {
emails {
subject
html # Access the HTML content here
}
}
}
QUERY;
$response = $client->query($query);
$emails = $response->getData()['inbox']['emails'];
foreach ($emails as $email) {
echo "Email Subject: " . $email['subject'] . "\n";
$htmlContent = $email['html'];
echo "HTML Content:\n$htmlContent\n";
// Extract all cid: references
if (preg_match_all('/cid:([a-zA-Z0-9-_]+)/', $htmlContent, $matches)) {
$cids = $matches[1]; // Extract only the CID values
echo "Found Content-ID (cid:) References:\n";
print_r($cids);
// Handle embedded images (e.g., base64 decoding or further processing)
foreach ($cids as $cid) {
echo "Processing embedded image with CID: $cid\n";
// In real scenarios, you might decode or handle the attached image here.
// This depends on your email library or how attachments are stored.
}
} else {
echo "No Content-ID references found in the email HTML.\n";
}
}
Обнаружение веб-маяков: Веб-маяки (также известные как пиксели отслеживания) — это обычно небольшие, невидимые изображения (часто размером 1x1 пиксель), которые встраиваются в письма для отслеживания факта открытия письма. Они обычно встречаются в тегах <img> с URL-адресами, ведущими на серверы отслеживания.
$htmlContent = "<html><body><img src='https://tracking.example.com/pixel?email=abc123' width='1' height='1' style='display:none;'></body></html>";
preg_match_all('/<img[^>]*src="([^"]+)"[^>]*width="1"[^>]*height="1"[^>]*style="display:none;"/', $htmlContent, $matches); // Match invisible 1x1 pixel images
print_r($matches); // Array will contain the URLs of web beacons Проверка исходных URL-адресов изображений: Вы можете отправлять HTTP-запросы к URL-адресам, найденным в атрибутах src тегов <img> , чтобы убедиться, что они загружаются корректно.
$htmlContent = "<html><body><img src='https://example.com/image.jpg' alt='Image'></body></html>";
preg_match_all('/<img[^>]*src="([^"]+)"/', $htmlContent, $matches); // Match all image URLs
foreach ($matches[1] as $imageUrl) {
$headers = get_headers($imageUrl); // Send HTTP request to the image URL
echo "Checking image: $imageUrl\n";
echo "Response: " . $headers[0] . "\n"; // Ensure the response is OK (e.g., 200 OK)
}
Комментарии (0)
Пока нет комментариев — будьте первым.